spring的后置处理器(未完结版)

学习spring源码也有一阶段时间了,是时候收货的季节了,打算写几篇博客,把自己的知识沉淀下来。在学习spring的源码之前,别人问我spring什么牛逼。我会毫不犹豫的说出AOP,IOC啊。但是看看源码之后,我觉得spring的后置处理器真牛逼,大名鼎鼎的AOP就利用了BeanPostProcessor和IOC容器建立了联系。不知道几个spring的后置处理器,你真不好意思说你学过spring。后置处理器就是LOL玩家姿态口中的"核心玩家"(不懂这个梗的可以忽略这句)。那么这篇博客将从下面这四个问题出发,从源码和应用的角度,剖析spring的后置处理器。

1.什么是后置处理器,有啥用?

2.spring什么时候注册的后置处理器?

3.spring什么时候执行后置处理器?

4.这些spring的后置处理器有哪些应用场景?

1.什么是后置处理器,有啥用?

大家想必都知道这样的一个设计原则:开闭原则,对扩展开放,对修改关闭。

那么spring的后置处理器就完美诠释了这一特性,简单来说,spring的后置处理器就是提供一个接口,让你干预bean的实例化,让你在bean的实例化前后扩展bean。

我们看下spring都提供了那些后置处理器。

先来看看大家都耳熟能详的一个接口:BeanPosterProcess

public interface BeanPostProcessor {

	/**
	 * 在bean初始化之前执行
	 */
	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

	/**
	 * 初始化之后
	 */
	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

}

这个就是BeanPostProcessor接口,就俩方法,简单到让人发指,但是他的实现类,多的让人发指(电脑屏幕有限,只能截取这些)

当然这些不可能都要掌握,我只能挑几个我熟悉的,常见的来学习下。我们来介绍几个常见的后置处理器

InstantiationAwareBeanPostProcessor

InstantiationAwareBeanPostProcessor接口继承BeanPostProcessor接口,它内部提供了3个方法,再加上BeanPostProcessor接口内部的2个方法,所以实现这个接口需要实现5个方法。InstantiationAwareBeanPostProcessor接口的主要作用在于目标对象的实例化过程中需要处理的事情,包括实例化对象的前后过程以及实例的属性设置

在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean()方法的Object bean = resolveBeforeInstantiation(beanName, mbdToUse);方法里面执行了这个后置处理器

1、postProcessBeforeInstantiation

在目标对象实例化之前调用,方法的返回值类型是Object,我们可以返回任何类型的值。由于这个时候目标对象还未实例化,所以这个返回值可以用来代替原本该生成的目标对象的实例(一般都是代理对象)。如果该方法的返回值代替原本该生成的目标对象,后续只有postProcessAfterInitialization方法会调用,其它方法不再调用;否则按照正常的流程走

2、postProcessAfterInstantiation

方法在目标对象实例化之后调用,这个时候对象已经被实例化,但是该实例的属性还未被设置,都是null。如果该方法返回false,会忽略属性值的设置;如果返回true,会按照正常流程设置属性值。方法不管postProcessBeforeInstantiation方法的返回值是什么都会执行

3、postProcessPropertyValues

方法对属性值进行修改(这个时候属性值还未被设置,但是我们可以修改原本该设置进去的属性值)。如果postProcessAfterInstantiation方法返回false,该方法不会被调用。可以在该方法内对属性值进行修改

4、postProcessBeforeInitialization&postProcessAfterInitialization

父接口BeanPostProcessor的2个方法postProcessBeforeInitialization和postProcessAfterInitialization都是在目标对象被实例化之后,并且属性也被设置之后调用的

SmartInstantiationAwareBeanPostProcessor

智能实例化Bean后置处理器(继承InstantiationAwareBeanPostProcessor)

1、determineCandidateConstructors

检测Bean的构造器,可以检测出多个候选构造器

2、getEarlyBeanReference

循环引用的后置处理器,这个东西比较复杂, 获得提前暴露的bean引用。主要用于解决循环引用的问题,只有单例对象才会调用此方法

3、predictBeanType

预测bean的类型

三、MergedBeanDefinitionPostProcessor

1、postProcessMergedBeanDefinition

缓存bean的注入信息的后置处理器,仅仅是缓存或者干脆叫做查找更加合适,没有完成注入,注入是另外一个后置处理器的作用

2.spring什么时候注册的后置处理器?(明天详细介绍)

3.spring什么时候执行后置处理器?(有些细节明天还要在深入,今天已经很晚了)

我的知识世界里,spring在bean的实例化前后,一个有8处调用了spring的后置处理器。我们从源码的角度来看,把这9处处理器执行过程,找出来,我今天就下播,睡觉,明天还要上班。

第一次:

我们看下这个InstantiationAwareBeanPostProcessor到底起着什么作用

如果该方法的返回值代替原本该生成的目标对象,后续只有postProcessAfterInitialization方法会调用,其它方法不再调用;否则按照正常的流程走

第二次:

SmartInstantiationAwareBeanPostProcessor这个后置处理器也非常重要,你的bean要用哪个构造方法去创建对象,都可以通过这个后置处理器来指定。我们来举个例子,在service下面提供两个构造方法,看看执行结果。

第一种情况是,提供两个构造方法有参和无参

打印的是no说明用的是这个无参的构造方法。

改变下这个类的构造方法,加一个注解

在构造方法上添加一个@Autowired的注解,就会调用另外一个构造方法,那我们把两个方法都加上注解呢,spring会知道用哪一个呢?

不好意思,spring也懵逼了,不知道到底用哪个,就报错了。这其实很容易理解,如果有两个美女(刘亦菲,刘诗诗)让你选择,你个贪心的家伙选择想两个都要,最后结果可想而知,你会J尽人亡。那么下面我们进入spring的源码来看下这到底是是真怎么实现的。

  

第三次

第四次

第五次

第六次

第七次

第八次

4.这些spring的后置处理器有哪些应用场景?(明天详细介绍)

知道了spring的后置处理器是什么,而且知道了spring的后置处理器在什么情况下调用,我们来用实际的案例来分析一下spring的这几种后置处理器(注意,前方高能,涉及的内容比较多,了解了,出去和面试官可以随便吹逼)

1.InstantiationAwareBeanPostProcessor的使用场景

我们都知道spring的动态代理

发布了62 篇原创文章 · 获赞 68 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/oldshaui/article/details/103358458