4、Spring源码之InstantiationAwareBeanPostProcessor

背景:

这里为什么会单独讲一下这个类呢??

①我在看Spring源码Bean的创建过程中 看到这个方法resolveBeforeInstantiation、看懂原理很有用

②我之前一次面试问 spring的Bean的创建流程 一般遵循 getBean---> doGetBean  -> createBean-->doCreateBean 这几个重要方法 有什么功能会打破这个流程嘛?当时不知道 太细了

③这在实际开发中看过别人写过类似代码 就是这个可能会用得到,当有类似需求时候你能想到这种方式。比如:你想要你的应用程序的某个类被spring容器管理是一个代理对象。你应该如何实现呢?InstantiationAwareBeanPostProcessor就是其中一个方式  


知识储备:

①Spring中什么是BeanPostProcessor、在什么阶段加入spring容器管理的
②SpringBean的整体创建流程要知道

注:源码跟踪示例使用配置文件方式 毕竟使用的方式千篇一律 有趣的原理才是万里挑一


源码跟踪:

提示:源码跟踪禁忌抠每一行代码 弄清源码功能整体的脉络思路就好

  • createBean方法里面的resolveBeforeInstantiation方法
    	// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
    	Object bean = resolveBeforeInstantiation(beanName, mbdToUse);

    这里主要干了什么事情呢? 官方注释【给Bean增强器一个返回代理而不是目标bean实例的机会】这句话翻译成大白话就是这个地方可能会发生proxy,也就是会篡改bean的原始类型,返回一个代理对象加入到spring容器中

     
  • 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) {
    					/**使用bean实例化前的后置处理器来处理目标bean*/
    					bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
    					/**如果bean不等于空,必然是发生了代理*/
    					if (bean != null) {
    						/**发生了代理,相当于bean完成了一次"实例化",正常的bean的实例化流程和初始化流程肯定走不了,
    						 * 因为走的是代理方法的实例化和初始化了,所以下面需要再调用一次当前bean的初始化增强器的后置处理方法
    						 */
    						bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
    					}
    				}
    			}
    			mbd.beforeInstantiationResolved = (bean != null);
    		}
    		return bean;
    	}


    ①hasInstantiationAwareBeanPostProcessors 意思如果容器中含有这样的InstantiationAwareBeanPostProcessors 那么将要执行applyBeanPostProcessorsBeforeInstantiation方法  

    注意:hasInstantiationAwareBeanPostProcessors这个属性是容器的一个属性 什么时候初始化呢 ?是在registerBeanPostProcessors方法
     
  • applyBeanPostProcessorsBeforeInstantiation有具体干了什么呢?
    ①遍历所有的BeanPostProcessor 找出InstantiationAwareBeanPostProcessors对象执行postProcessBeforeInstantiation方法

    ②我们分析下postProcessBeforeInstantiation参数 将要实例化的Bean的class和beanName

    注意:容器中BeanPostProcessor 什么时候初始化呢 ?是在registerBeanPostProcessors方法
  • 既然postProcessBeforeInstantiation方法返回代理对象 那么 我自己编写一个类 实现InstantiationAwareBeanPostProcessors接口、重写postProcessBeforeInstantiation方法、在这个方法里 使用cglib或者jdk返回一个代理对象不就可以了嘛 那么接下里自己实现一下

案例:

  • 配置文件
    	<bean id="myBeanPostProcessor" class="com.zhangfuyin.bpp.MyBeanPostProcessor"/>
    
    
    	<bean id="instantiationAwareBean" class="com.zhangfuyin.bpp.InstantiationAwareBean"/>
    

  • java
    public class MyBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
    	@Override
    	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
    		if(beanClass == InstantiationAwareBean.class){
    			Enhancer enhancer = new Enhancer();
    			enhancer.setSuperclass(beanClass);
    			enhancer.setCallback(new DistributedLockInterceptor());
    			return  enhancer.create();
    		}
    		return null;
    	}
    }
    
    
    =============================================================================
    
    public class DistributedLockInterceptor implements MethodInterceptor {
    	@Override
    	public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
    		Class<?>[] classes = method.getParameterTypes();
    
    		System.out.println("==============DistributedLockInterceptor.invoke before");
    		Object rtnObj = methodProxy.invokeSuper(o,objects);
    		System.out.println("==============DistributedLockInterceptor.invoke after");
    		return rtnObj;
    	}
    }
    
    
    =============================================================================
    
    public class InstantiationAwareBean {
    
    	public void doSomething(){
    		System.out.println("==============doSomething====================");
    	}
    }

  • 测试
     
    public  static void main(String agrs[]){
    		ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("instantiationAwareBeanPostProcessor.xml");
    		InstantiationAwareBean instantiationAwareBean = ac.getBean(InstantiationAwareBean.class);
    		instantiationAwareBean.doSomething();
    }

    打印结果:执行目标方法  会进入代理类的方法拦截器 证明代理类被注入spring容器
    ==============DistributedLockInterceptor.invoke before
    ==============doSomething====================
    ==============DistributedLockInterceptor.invoke after

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值