发布时间:2025-12-10 19:23:29 浏览次数:25
spring beanpostprocess_Bean @session水稻:这两天看了BeanDefinition和BeanFactoryPostProcessor还有BeanPostProcessor的源码。要不要了解一下菜瓜:sixsixsix,大佬请讲水稻:上次我们说SpringIOC容器是一个典型的工厂模式假如我们把Spring比作一个生产模型的大工
水稻:这两天看了BeanDefinition和BeanFactoryPostProcessor还有BeanPostProcessor的源码。要不要了解一下
菜瓜:six six six,大佬请讲
水稻:上次我们说SpringIOC容器是一个典型的工厂模式
假如我们把Spring比作一个生产模型的大工厂,那么.class文件就是原材料。而BeanDefinition就是创建模型的模具。不管是传统的XML还是后面的注解,Spring在启动的时候都会创建一个扫描器去扫描指定目录下的.class文件,并根据文件的注解,实现的接口以及成员变量将其封装一个个的BeanDefinition。 比较重要的属性有id,class,构造函数封装类,属性封装类,factoryMethod等 在对象初始化之前Spring会完成BeanDefinition对象的解析并将其装入List容器beanDefinitionNames中,然后开始遍历该容器并根据BeanDefinition创建对象菜瓜:sodasinei,BeanDefinition我了解了。它是创建bean的模板,类似于java创建对象依赖的class一样。那还有两个很长的单词是啥呢?
水稻:忽略掉后面老长的后缀,我们看BeanFactory和Bean是不是很亲切。PostProcessor被翻译成后置处理器,暂且我们把它看成是处理器就行
BeanFactory是bean工厂,它可以获取并修改BeanDefinition的属性,进而影响后面创建的对象。 Bean就是Spring的对象,这些个处理器才是真正处理bean对象的各个环节的工序,包括属性,注解,方法菜瓜:有了模糊的概念,不明觉厉
水稻:来,看demo
package com.vip.qc.postprocessor;import org.springframework.beans.BeansException;import org.springframework.beans.MutablePropertyValues;import org.springframework.beans.factory.config.BeanDefinition;import org.springframework.beans.factory.config.BeanFactoryPostProcessor;import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;import org.springframework.stereotype.Component;/*** 获取初始化好的BeanFactory,此时还未进行bean的实例化** @author QuCheng on 2020/6/14.*/@Componentpublic class BeanFactoryPostProcessorT implements BeanFactoryPostProcessor {public static final String BEAN_NAME = "processorT";@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {BeanDefinition initializingBeanT = beanFactory.getBeanDefinition(BEAN_NAME);MutablePropertyValues propertyValues = initializingBeanT.getPropertyValues();String pName = "a";System.out.println("BeanFactoryPostProcessor a " + propertyValues.getPropertyValue(pName) + " -> 1");propertyValues.addPropertyValue(pName, "1");}}package com.vip.qc.postprocessor;import org.springframework.beans.BeansException;import org.springframework.beans.factory.config.BeanPostProcessor;import org.springframework.stereotype.Component;/*** @author QuCheng on 2020/6/14.*/@Componentpublic class BeanPostProcessorT implements BeanPostProcessor {public static final String beanNameT = "processorT";@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {if (beanNameT.equals(beanName)) {ProcessorT processorT = ((ProcessorT) bean);System.out.println("BeanPostProcessor BeforeInitialization a:" + processorT.getA() + "-> 3");processorT.setA("3");}return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (beanNameT.equals(beanName)){ProcessorT processorT = ((ProcessorT) bean);System.out.println("BeanPostProcessor AfterInitialization a:" + processorT.getA() + "-> 4");processorT.setA("4");}return bean;}}package com.vip.qc.postprocessor;import org.springframework.stereotype.Component;/*** @author QuCheng on 2020/6/14.*/@Componentpublic class ProcessorT {public ProcessorT() {System.out.println("ProcessorT 无参构造 a:" + a + "-> 2" );a = "2";}private String a;public String getA() {return a;}public void setA(String a) {this.a = a;}@Overridepublic String toString() {return "ProcessorT{" +"a='" + a + '\'' +'}';}}// 测试类@Testpublic void test() {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.vip.qc.postprocessor");ProcessorT processorT = (ProcessorT) context.getBean("processorT");System.out.println(processorT);}// 结果BeanFactoryPostProcessor a null -> 1ProcessorT 无参构造 a:null-> 2BeanPostProcessor BeforeInitialization a:1-> 3BeanPostProcessor AfterInitialization a:3-> 4ProcessorT{a='4'}【正版授权,激活自己账号】:Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
BeanFactoryPostProcessor在对象还未初始化前可以拿到对象的BeanDefinition对其设置属性值 过程中我们分别对属性a设置了1,2,3,4的值。最后我们拿到的值为4菜瓜:好像看懂了。BeanFactoryPostProcessor可以拿到BeanFactory对象,获取里面所有的BeanDefinition并可对其进行干预。BeanPostProcessor其实是在bean已经被创建完成之后进行加工操作
水稻:没错。这是我们自己进行干预的demo。限于篇幅有限,你可以去看一下Spring自己对于这两个接口的实现源码。比较重要的推荐下面几个
ConfigurationClassPostProcessor 实现BeanFactoryPostProcessor子接口 完成对@Configuration、@Component、@ComponentScan、@Bean、@Import、@ImportSource注解的搜集和解析 @Bean注解会被封装成所在Bean的BeanDefinition中的factoryMethod属性中,单独进行实例化 CommonAnnotationBeanPostProcessor 实现BeanPostProcessor 完成@PostConstruct@PreDestroy@Resource注解的搜集和解析工作 @PostConstruct会在对象初始化且属性渲染完成后进行 @Resource注解(参照下面) AutowiredAnnotationBeanPostProcessor实现BeanPostProcessor 完成@Autowired@Value注解的搜集和解析工作 在对象初始化完成之后会先进行注解的搜集,然后进行属性渲染调用populateBean方法,使用策略模式调用实现接口对注解进行解析,有@Autowired和@Value注解会调用getBean方法发起对依赖属性的注入 AbstractAutoProxyCreator的入口类也是实现的BeanPostProcessor菜瓜:你放心,我不会看的。这么复杂的东西,听着都费劲
水稻:不愧是你!有机会聊bean的生命周期的时候咱们还会说到这些东西。到时候再刷一遍
总结:
BeanDefinition是spring容器创建对象的模板,定义了bean创建的细节 BeanFactoryPostProcessor可以拿到整个容器对象,当然也能修改BeanDefinition,所以能直接操作bean的创建 BeanPostProcessor执行的时候bean已经创建完成了,我们可以拿到想要的对象进行干预和设值等操作