行业知识
Spring之BeanPostProcessor
什么是BeanPostProcessor
BeanPostProcessor从本质上讲也是一个bean,它的实例化在普通bean之前,然后作用于普通bean。BeanPostProcessor可以作用于普通bean生命周期的以下几个阶段:
- postProcessBeforeInitialization
- postProcessAfterInitialization
- postProcessBeforeInstantiation
- postProcessAfterInstantiation
- postProcessPropertyValues
- postProcessMergedBeanDefinition
- ......
BeanPostProcessor实例化时机及排序问题
AbstractApplicationContext#refresh
具体实例化BeanPostProcessor的方法为registerBeanPostProcessors,该方法中有很多重复代码,大体可以分为查找、排序、注册三个阶段。具体排序规则如下:
- 实现了 PriorityOrdered 且未实现 MergedBeanDefinitionPostProcessor 接口的BeanPostProcessor
- 实现了 Ordered 且未实现 MergedBeanDefinitionPostProcessor 接口的BeanPostProcessor
- 未实现了 PriorityOrdered、Ordered、MergedBeanDefinitionPostProcessor 接口的BeanPostProcessor
- 实现了 PriorityOrdered、MergedBeanDefinitionPostProcessor 接口的BeanPostProcessor
- 实现了Ordered、MergedBeanDefinitionPostProcessor 接口的BeanPostProcessor
- 未实现了 PriorityOrdered、Ordered 接口实现 MergedBeanDefinitionPostProcessor 接口的BeanPostProcessor
Spring默认注册的一些BeanPostProcessor
BeanPostProcessor对普通bean生命周期的影响
1.InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
AbstractAutowireCapableBeanFactory#createBean
我们看一下注释:给bpp一个机会返回一个代理的对象,这很显然是一个扩展点,我们点进去看看究竟
只要完成上述这三个条件,就不用执行后面的实例化流程了。比如属性填充(populateBean),方法回调等。
自定义一些组件,满足上述三个条件
创建一个普通类ModelJ ,类上标记@Component注解
package com.test.spring.model;import org.springframework.stereotype.Component;@Componentpublic class ModelJ {}创建一个实现ApplicationContextAware接口和使用@Autowired注入属性的类
package com.test.spring.model;import org.springframework.beans.BeansException;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;import org.springframework.stereotype.Component;@Componentpublic class ModelI implements ApplicationContextAware { @Autowired private ModelJ modelJ; private ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; }}创建配置类AppConfig
package com.test.spring.config;import org.springframework.context.annotation.ComponentScan;/** * 这里可以不用加@Configuration * AnnotationConfigApplicationContext会将构造方法注入的类,解析成bd */@ComponentScan("com.test.spring")public class AppConfig {}创建一个BeanFactoryPostProcessor
@Componentpublic class SeventhBeanFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor { @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { if (registry.containsBeanDefinition("modelI")) { // 这里是ScannedGenericBeanDefinition 还不能强转成RootBeanDefinition ScannedGenericBeanDefinition scannedGenericBeanDefinition = (ScannedGenericBeanDefinition) registry.getBeanDefinition("modelI"); RootBeanDefinition beanDefinition = new RootBeanDefinition(); beanDefinition.setBeanClassName(scannedGenericBeanDefinition.getBeanClassName()); try { // 这个属性是包可见,利用反射强行设置了一下 Field beforeInstantiationResolved = beanDefinition.getClass().getDeclaredField("beforeInstantiationResolved"); beforeInstantiationResolved.setAccessible(true); beforeInstantiationResolved.set(beanDefinition, true); } catch (Exception e) { throw new RuntimeException(e); } registry.registerBeanDefinition("modelI", beanDefinition); } } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { }}该BeanFactoryPostProcessor将BeanDefinition对象的 beforeInstantiationResolved 属性值修改为true,满足第一条件
创建一个BeanPostProcessor
package com.test.spring.bpp;import com.test.spring.model.ModelI;import org.springframework.beans.BeansException;import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor;import org.springframework.stereotype.Component;@Componentpublic class FirstBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor { @Override public Object postProcessBeforeInstantiation(Class beanClass, String beanName) { if (beanClass == ModelI.class) { try { ModelI modelI = (ModelI) beanClass.newInstance(); return modelI; } catch (Exception e) { throw new RuntimeException(e); } } else { return SmartInstantiationAwareBeanPostProcessor.super.postProcessBeforeInstantiation(beanClass, beanName); } } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { // 这个父类方法就是返回原对象,直接使用父类方法 return SmartInstantiationAwareBeanPostProcessor.super.postProcessAfterInitialization(bean, beanName); }}该BeanPostProcessor的postProcessBeforeInstantiation方法,返回一个非空的值,满足第二条件。同时该BeanPostProcessor的postProcessAfterInitialization方法直接调用父类对象(该父类方法直接返回原对象),满足第三条件
运行main方法,查看运行结果
我们可以观察到属性注入方法(populateBean)和 回调方法(setApplicationContext)都没有执行,spring在执行完BeanPostProcessor的postProcessAfterInitialization方法后,就直接返回了
2. MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition
这个类我们拿其子类 AutowiredAnnotationBeanPostProcessor 举例
AutowiredAnnotationBeanPostProcessor主要是查找所有bean中的注入点,随后在spring生命周期的某个节点将查找到的注入点,注入到指定的bean中
Spring如何定义注入点
简单来说,就是方法或者属性上存在@Autowired注解
举例演示
创建一个类ModelK
package com.test.spring.model;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;@Componentpublic class ModelK { @Autowired private ModelI modelI; private ModelJ modelJ; @Autowired public void setModelJ(ModelJ modelJ) { this.modelJ = modelJ; }}运行main方法,查看运行结果
3.InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation
这个类在populateBean方法中,如果方法返回false,表示这个bean不执行属性填充操作
举例演示
创建一个类ModelL
package com.test.spring.model;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;@Componentpublic class ModelL { @Autowired private ModelJ modelJ;}创建一个BeanPostProcessor
package com.test.spring.bpp;import org.springframework.beans.BeansException;import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor;import org.springframework.stereotype.Component;@Componentpublic class SecondBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor { @Override public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException { if ("modelL".equals(beanName)) { return false; } else { return SmartInstantiationAwareBeanPostProcessor.super.postProcessAfterInstantiation(bean, beanName); } }}运行main方法,查看运行结果
忽略注入属性modelJ
4.BeanPostProcessor#postProcessBeforeInitialization
这个方法前后及其子类实现,一般都是一些钩子函数,简单罗列一下
- 方法之前
- AbstractAutowireCapableBeanFactory#invokeAwareMethods
- setBeanName
- setBeanClassLoader
- setBeanFactory
- AbstractAutowireCapableBeanFactory#invokeAwareMethods
- 子类实现
- InitDestroyAnnotationBeanPostProcessor$LifecycleElement
- @PostConstruct标注的方法
- ApplicationContextAwareProcessor#invokeAwareInterfaces
- setEnvironment
- setEmbeddedValueResolver
- setResourceLoader
- setApplicationEventPublisher
- setMessageSource
- setApplicationStartup
- setApplicationContext
- InitDestroyAnnotationBeanPostProcessor$LifecycleElement
- 方法之后
- AbstractAutowireCapableBeanFactory#invokeInitMethods
- 处理实现InitializingBean接口的bean
5.BeanPostProcessor#postProcessAfterInitialization
在这一阶段,最常见的作用就是动态代理。比如@EnableTransactionManagement注解会注入一个类型为 InfrastructureAdvisorAutoProxyCreator 的BeanPostProcessor,这个类的祖父类(AbstractAutoProxyCreator)的方法实现(postProcessAfterInitialization)就是对满足条件的bean进行动态代理。相关源码如下:
PS : @EnableAspectJAutoProxy注解和@EnableAsync注解注入的BeanPostProcessor,也会在这一阶段对满足条件的bean进行动态代理
总结
BeanPostProcessor的作用很强大,但是也很危险,如果不加条件判断要处理的特定bean,所有的bean的都会受影响,所有的bean的都会受影响,所有的bean的都会受影响,重要的事情说三遍。
- AbstractAutowireCapableBeanFactory#invokeInitMethods
上一篇:服务器怎么调披风?