spring中BeanPostProcessor之一:InstantiationAwareBeanPostProcessor
https://www.cnblogs.com/teach/p/12639363.html
spring中BeanPostProcessor之一:InstantiationAwareBeanPostProcessor(01)
在spring中beanPostProcessor绝对是开天辟地的产物,给了程序员很多自主权,beanPostProcessor即常说的bean后置处理器。
一、概览
先来说下InstantiationAwareBeanPostProcessor,这个后置处理器是BeanPostProcessor的子接口,继承自BeanPostProcessor,先看下BeanPostProcessor中的方法,
再看下InstantiationAwareBeanPostProcessor中的方法,
可见InstantiationAwareBeanPostProcessor扩展了BeanPostProcessor接口,并且新增了4个方法,今天先看postProcessAfterInstantiation方法,
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException { return true; }
改方法有默认的返回值为true。
二、详述
InstantiationAwareBeanPostProcessor中的postProcessAfterInstantiation方法的作用是什么那,用在什么地方。在看spring源码的时候看到属性注入这段代码,其中属性注入是在populateBean方法中完成,在此方法中便出现了postProcessAfterInstatiation方法的调用,这里只贴出populateBean方法中和这块有关系的代码,
boolean continueWithPropertyPopulation = true; //调用beanFactory中已注册的beanPostProcessors即bean后置处理器,判断是否为InstantiationAwareBeanPostProcessor的类型,如果是执行postProcessAfterInstantiation if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; //如果返回值为false才会进到下面的赋值操作,从而下方的1处才会为true,则属性注入才会中断 if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { continueWithPropertyPopulation = false; break; } } } } //1 if (!continueWithPropertyPopulation) { return; }
上面这段逻辑就是来循环已经注册的beanPostProcessor,找到是InstantiationAwareBeanPostProcessor的类型,并执行其postProcessAfterInstantiation方法,通过查看已注册的beanPostProcessor发现其返回值均为true,通过上面的分析,只有postProcessAfterInstantiation方法返回false,populateBean方法才会返回,属性注入才会中断,即不会注入值。
怎么才能保证postProcessAfterInstantiation方法返回false那,这里只有自己向spring注册一个InstantiationAwareBeanPostProcessor的后置处理器,下面是我的一个后置处理器,
package cn.com.my.test; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor; import org.springframework.stereotype.Component; @Component public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor { @Override public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException { // TODO Auto-generated method stub System.out.println("beanName:"+beanName); if("userService".equals(beanName)) { return false; } return InstantiationAwareBeanPostProcessor.super.postProcessAfterInstantiation(bean, beanName); } }
自定义的beanPostProcessor仅实现了postProcessAfterInstantiation方法,上面的代码逻辑中,可以看到只有beanName为userService的时候,改方法才会返回false,其他情况下调用的接口方法,返回默认值true。
下面看我的测试类,
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.roleService:"+us.getRoleService()); } }
下面是我的UserService类,
package cn.com.my.test; import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor; import org.springframework.stereotype.Component; @Component public class UserService { @Autowired private RoleService roleService; public RoleService getRoleService() { return roleService; } public void setRoleService(RoleService roleService) { this.roleService = roleService; } }
从UserService类中,可以看出有一个加了注解的roleService属性,正常情况下会自动注入改属性,但在我自定义的beanPostProcessor之后,看下面的结果
神奇的事情,发生了us.roleService的属性返回的null。
这是为什么那,我们再看populateBean中的这段代码,
boolean continueWithPropertyPopulation = true; //调用beanPostProcessors即bean后置处理器, if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { continueWithPropertyPopulation = false; break; } } } } if (!continueWithPropertyPopulation) { return; }
由于,我们向beanFactory中注册了一个beanPostProcessor,所以这里循环的时候肯定会执行我的postProcessAfterInstantiation后置处理器,而我在后置处理器中进行了判断,即在给beanName为userService进行属性注入的时候postProcessAfterInstantiation方法会返回false,那么上面的continueWithPropertyPopulation便为false,导致会进入到下面的if,方法直接返回,属性注入便会中止,所以UserService类中的roleService的值为null。
三、适用场合
什么时候需要实现InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation方法那,如果不想使用spring的自动注入(前提是已经使用了@Autowired注解),则对于特殊的bean则可以注册一个beanPostProcessor使其不进行注入,使用自己的方式进行注入。
spring中BeanPostProcessor之一:InstantiationAwareBeanPostProcessor(02)
在上篇博客中写道了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的一个实现。