在上篇博客中写道了bean后置处理器InstantiationAwareBeanPostProcessor,只介绍了其中一个方法的作用及用法,现在来看postProcessBeforeInstantiation方法。

一、概述

postProcessBeforeInstantiation方法定义在InstantiationAwareBeanPostProcessor接口中,方法的定义如下,

@Nullable
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
return null;
}

从上面的代码中可以看到该方法默认返回null。

二、详述

postProcessBeforeInstantiation方法是用来做什么的,在看源码的过程中,在createBean方法中找到了该方法的调用,下面只贴出相关代码,

try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
//1、调用beanPostProcessor即bean的后置处理器,这里会调用2次后置处理器
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}

在resolveBeforeInstantiation方法中进行了调用,resolveBeforeInstantiation方法返回值如果不为null,则该方法直接返回bean,也就是说resolveBeforeInstantiation方法至关重要,下面是resolveBeforeInstantiation方法,

@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
//如果是InstantiationAwareBeanPostProcessor的实例,则执行其postProcessBeforeInstantiation方法
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
//如果上面的postProcessBeforeInstantiation方法返回值不为null,则执行所有beanPostProcessor的postProcessAfterInitialization方法
//bean不为null,则说明postProcesBeforeInstantiation方法中的返回值是一个不为null的对象
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}

在resolveBeforeInstantiation方法中首先调用了applyBeanPostProcessorsBeforeInstantiation方法,该方法中便会调用InstantiationAwareBeanPostProcessor接口中的postProcessBeforeInstantiation方法,且如果applyBeanPostPorcessorsBeforeInstantiation方法返回值不为null,才会调用applyBeanPostProcessAfterIntialization方法,下面先看applyBeanPostProcessorsBeforeInstantiation方法

@Nullable
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
return null;
}

从上面方法的定义看到,该方法会遍历benaFactory中的beanPostProcessor,并且判断是否为InstantiationAwareBeanPostPrecessor的类型,如果是执行其postProcessBeforeInstantiation方法,这里默认注册的beanPostProcessor该方法的返回值均为null。稍后自定义一个BeanPostProcessor实现InstantiationAwareBeanPostProcessor接口。

下面看applyBeanPostProcessAfterIntializtion方法,

@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException { Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}

改方法的逻辑是遍历beanFactory中的所有的beanPostProcessor,执行其postProcessAfterInitialization方法,该方法定义在BeanPostProcessor接口中,默认返回bean,如下,

@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}

从上面可以看出默认返回的是bean参数的值,也就是如果该方法未实现则默认返回参数中的bean。

再次回到resolveBeforeInstantiation方法,再看其逻辑有以下几种方法返回值的组合,

1、applyBeanPostProcessBeforeInstantiation返回值为null,则resolveBeforeInstantiation方法返回null;

2、applyBeanPostProcessBeforeInstantiation返回值bean不为null,applyBeanPostProcessAfterInitialization方法返回值为null,则resolveBeforeInstantiationf方法返回值为bean;

3、applyBeanPostProcessBeforeInstantiation返回值bean不为null,applyBeanPostProcessAfterInitialization方法返回值bean1不为为null,则resolveBeforeInstantiationf方法返回值为bean1;

从resolveBeforeInstantiation方法分析,该方法的返回值,直接决定了createBean方法的返回值,也就是说applyBeanPostProcessBeforeInstantiation方法返回的bean不为null,下面的方法不会执行。

再来看调用resolveBeforeInstantiation方法时的注释

// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);

大体意思时给BeanPostProcessor一个机会返回代理对象而不是目标对象的实例,所以这里resolveBeforeInstantiation方法返回的必然时一个代理对象(JDK和CGLib)。看下面的例子

自定义的BeanPostProcessor实现了InstantiationAwareBeanPostProcessor

package cn.com.my.test;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.stereotype.Component; import net.sf.cglib.proxy.Enhancer;
@Component
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor { @Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// TODO Auto-generated method stub if("userService".equals(beanName)) { UserService us=(UserService)bean; Enhancer enhancer = new Enhancer();
//设置目标类的字节码文件
enhancer.setSuperclass(UserService.class);
//设置回调函数
enhancer.setCallback(new MyMethodInterceptor()); //这里的creat方法就是正式创建代理类
UserService proxyUs = (UserService)enhancer.create();
return proxyUs;
}
return InstantiationAwareBeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
}
}

当beanName等于userUservice时返回的是经过cglib代理后的对象。在MyInstantiationAwareBeanPostProcessor类中仅实现了postProcessBeforeInitialization方法,未实现postProcessAfterInitialization方法,所以resolveBeforeInstantiation方法的返回值即未postProcessBeforeInitialization方法的返回值,在上面的类中就是使用cglib代理后的UserService实例。

代理类MyMethodInterceptor,实现cglib的MethodInterceptor接口

package cn.com.my.test;

import java.lang.reflect.Method;

import org.springframework.cglib.proxy.MethodProxy;

import net.sf.cglib.proxy.MethodInterceptor;

public class MyMethodInterceptor implements MethodInterceptor{

    @Override
public Object intercept(Object arg0, Method arg1, Object[] arg2, net.sf.cglib.proxy.MethodProxy arg3)
throws Throwable {
// TODO Auto-generated method stub
Object object = arg3.invokeSuper(arg0, arg2);
return object;
}
}

下面是测试类

package cn.com.my.test;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Test {

    public static void main(String[] args) {
// TODO Auto-generated method stub AnnotationConfigApplicationContext ac=new AnnotationConfigApplicationContext(Config.class); UserService us=ac.getBean(UserService.class);
System.out.println("us:"+us); } }

看下面的结果,

us:cn.com.my.test.UserService$$EnhancerByCGLIB$$ffa582b4@5fe94a96

返回的是UserService的一个经过cglib代理后的对象。到这里发现真好强大,返回的一个代理对象。

三、适用场合

实现InstantiationAwareBeanPostProcessor接口的postProcessBeforeInitialization方法,通过返回一个代理对象的方式,达到改变目标类类型的目的。在不想改变现有类的逻辑而又想借助现有类实现其他功能,就可以使用这种方式。像AOP就是这种实现,AnnotationAwareAspectJAutoProxyCreator类便是InstantiationAwareBeanPostProcessor的一个实现。

原创不易,有不当之处,欢迎指正,谢谢!

spring中BeanPostProcessor之一:InstantiationAwareBeanPostProcessor(02)的更多相关文章

  1. spring中BeanPostProcessor之一:InstantiationAwareBeanPostProcessor(01)

    在spring中beanPostProcessor绝对是开天辟地的产物,给了程序员很多自主权,beanPostProcessor即常说的bean后置处理器. 一.概览 先来说下Instantiatio ...

  2. Spring中BeanPostProcessor

    Spring中BeanPostProcessor 前言: 本文旨在介绍Spring动态配置数据源的方式,即对一个DataSource的配置诸如jdbcUrl,user,password,driverC ...

  3. spring中BeanPostProcessor之三:InitDestroyAnnotationBeanPostProcessor(01)

    在<spring中BeanPostProcessor之二:CommonAnnotationBeanPostProcessor(01)>一文中,分析到在调用CommonAnnotationB ...

  4. spring中BeanPostProcessor之四:AutowiredAnnotationBeanPostProcessor(01)

    在<spring中BeanPostProcessor之二:CommonAnnotationBeanPostProcessor(01)>中分析了CommonAnnotationBeanPos ...

  5. spring中BeanPostProcessor之一:InstantiationAwareBeanPostProcessor(03)

    前面介绍了InstantiationAwareBeanPostProcessor后置处理器的postProcessBeforeInstantiation和postProcessAfterInstant ...

  6. spring中BeanPostProcessor之二:CommonAnnotationBeanPostProcessor(01)

    在上篇博客中分享了InstantiationAwareBeanPostProcessor接口中的四个方法,分别对其进行了详细的介绍,在文末留下了一个问题,那就是postProcessPropertie ...

  7. spring(三):spring中BeanPostProcessor的使用

    spring中实现BeanPostProcessor的后置处理器 ApplicationContextAwareProcessor 进入该实现类内部 可以看到:该类帮我们组建IOC容器,判断我们的be ...

  8. 通过BeanPostProcessor理解Spring中Bean的生命周期

    通过BeanPostProcessor理解Spring中Bean的生命周期及AOP原理 Spring源码解析(十一)Spring扩展接口InstantiationAwareBeanPostProces ...

  9. Spring中的BeanPostProcessor

    一.何谓BeanProcessor BeanPostProcessor是SpringFramework里非常重要的核心接口之一,我先贴出一段源代码: /* * Copyright 2002-2015 ...

随机推荐

  1. MVC09

    1.委托(delegate)调用静态方法 委托类似于C++中的函数指针. 某方法仅仅在执行的时候才能确定是否被调用. 是实现事件和回调函数的基础. 面向对象,安全性高. using System; u ...

  2. RabbitMQ面试题集锦(精选)(另附思维导图)

    1.使用RabbitMQ有什么好处? 1.解耦,系统A在代码中直接调用系统B和系统C的代码,如果将来D系统接入,系统A还需要修改代码,过于麻烦! 2.异步,将消息写入消息队列,非必要的业务逻辑以异步的 ...

  3. Redis01——Redis究竟支持哪些数据结构

    Redis已经越来越多地应用到互联网技术中,而关于Redis的相关问题,也成为面试中必不可少的一部分,本文开始将会逐渐把我了解到的关于Redis的一些面试问题整理出来,供各位参考,如有不对之处,烦请指 ...

  4. 写一个scrapy中间件--ip代理池

    middleware文件 # -*- coding: utf-8 -*- # Define here the models for your spider middleware # See docum ...

  5. npm run build时卡住不动了...

    在build文件夹里有个check-versions.js. if (shell.which('npm')) { versionRequirements.push({ name: 'npm', cur ...

  6. (转)const的内部链接属性(C++中适用)

    转载自:http://xiangwangfeng.com/2011/05/02/const%E7%9A%84%E5%86%85%E9%83%A8%E9%93%BE%E6%8E%A5%E5%B1%9E% ...

  7. 记一次修改mysql密码

    因为马大哈的原因,没有记录自己服务器mysql的密码,试来试去试不出来只好选择重置密码. 直接上命令: 首先 vim /etc/my.cnf 在my.cnf文件中,在[mysqld]的段中加上 ski ...

  8. javaScript 基础知识汇总 (十三)

    1.Class 在JavaScript中 calss即类是一种函数 基本语法 class Myclass{ constructor(){} method1(){} method2(){} method ...

  9. 创建和存储 cookie

    在这个例子中我们要创建一个存储访问者名字的 cookie.当访问者首次访问网站时,他们会被要求填写姓名.名字会存储于 cookie 中.当访问者再次访问网站时,他们就会收到欢迎词. 首先,我们会创建一 ...

  10. ASP.NET Core - 在ActionFilter中使用依赖注入

    上次ActionFilter引发的一个EF异常,本质上是对Core版本的ActionFilter的知识掌握不够牢固造成的,所以花了点时间仔细阅读了微软的官方文档.发现除了IActionFilter.I ...