飞道的博客

Springboot扩展点之InstantiationAwareBeanPostProcessor

493人阅读  评论(0)

Springboot扩展点系列实现方式、工作原理集合:

Springboot扩展点之ApplicationContextInitializer

Springboot扩展点之BeanFactoryPostProcessor

Springboot扩展点之BeanDefinitionRegistryPostProcessor

Springboot扩展点之BeanPostProcessor

Springboot扩展点之InstantiationAwareBeanPostProcessor

Springboot扩展点之SmartInstantiationAwareBeanPostProcessor

Springboot扩展点之ApplicationContextAwareProcessor

Springboot扩展点之@PostConstruct

Springboot扩展点之InitializingBean

Springboot扩展点之SmartInitializingSingleton

Springboot扩展点之CommandLineRunner和ApplicationRunner

Springboot扩展点之FactoryBean

Springboot扩展点之DisposableBean

Springboot扩展点系列之终结篇:Bean的生命周期

前言

前面介绍了Springboot的扩展点之BeanPostProcessor,再来介绍另一个扩展点InstantiationAwareBeanPostProcessor就容易多了。因为InstantiationAwareBeanPostProcessor也属于Bean级的后置处理器,还继承于BeanPostProcessor,因此InstantiationAwareBeanPostProcessor除了可以实现BeanPostProcessor的扩展外,又额外增加了三个扩展点,这篇文章也是围绕这三个扩展点展示,主要介绍InstantiationAwareBeanPostProcessor扩展接口的功能特性、实现方式、工作原理、和应用场景,BeanPostProcessor扩展部分可以翻看前面的文章Springboot的扩展点之BeanPostProcessor

功能特性

1、虽然InstantiationAwareBeanPostProcessor继承于BeanPostProcessor,但是InstantiationAwareBeanPostProcessor的执行时机要稍早于BeanPostProcessor;

2、InstantiationAwareBeanPostProcessor有三个扩展方法,分别是:postProcessBeforeInstantiation()、postProcessAfterInstantiation()、postProcessProperties();

3、postProcessBeforeInstantiation()在Spring中Bean实例化前触发执行;

4、postProcessAfterInstantiation()、postProcessProperties()在Spring中Bean实例化后,属性注入前触发执行;

5、InstantiationAwareBeanPostProcessor继承于BeanPostProcessor的postProcessBeforeInitialization()和postProcessAfterInitialization()则在Spring中Bean实例化、属性注入完成后触发执行;

6、postProcessBeforeInstantiation()扩展点可以自定义个性化的Bean来替换掉目标Bean,需要注意的是替换掉目标Bean后,postProcessAfterInstantiation()会执行,其他的扩展点将不再触发;

7、postProcessAfterInstantiation()的返回值为布尔类型,如果返回值为true,则第三个扩展点postProcessProperties()会继续执行;如果返回值为false,则第三个扩展点postProcessProperties()将不再执行;

8、postProcessProperties()扩展点可以在目标Bean实例化后,属性注入前,对要注入的属性值内容进行更改,以替换掉原来的属性值;

实现方式

总的来说InstantiationAwareBeanPostProcessor扩展点的实现方式很简单,实现接口,重写相应的方法实现扩展逻辑,并用@Component注解标记实现类,其余的由Spring自动完成。下面通过示例逐步详细介绍:

1、定义一个Controller类(ExampleController),通过setter方法注入属性ExampService;


   
  1. @RestController
  2. @RequestMapping("/example")
  3. @Slf4j
  4. public class ExampleController {
  5. private String creator= "gaox";
  6. private ExampleService exampleService;
  7. @Autowired
  8. public void setExampleService (ExampleService exampleService) {
  9. this.exampleService = exampleService;
  10. log.info( "----ExampleController内的exampleService属性被注入");
  11. }
  12. public void setCreator (String creator) {
  13. this.creator = creator;
  14. log.info( "----ExampleController内的creator属性被注入");
  15. }
  16. public String getCreator () {
  17. return creator;
  18. }
  19. public ExampleController () {
  20. log.info( "----ExampleController无参构造方法被执行");
  21. }
  22. }

2、定义ExampleService类,以便作为引用属性注入到ExampleController中;


   
  1. @Service
  2. @Slf4j
  3. public class ExampleService {
  4. public ExampleService () {
  5. log.info( "----ExampleService无参构造方法被执行");
  6. }
  7. public void test (){
  8. System.out.println( "test");
  9. }
  10. }

3、定义InstantiationAwareBeanPostProcessor接口的实现类示例类MyInstantiationAwareBeanPostProcessor,并重写InstantiationAwareBeanPostProcessor接口的三个扩展方法和继承于BeanPostProcessor接口的两个扩展方法;


   
  1. @Component
  2. @Slf4j
  3. public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
  4. @SneakyThrows
  5. @Override
  6. public Object postProcessBeforeInstantiation (Class<?> beanClass, String beanName) throws BeansException {
  7. if (beanName.equals( "exampleController")) {
  8. log.info( "----postProcessBeforeInstantiation被执行:" + beanName);
  9. return null;
  10. }
  11. return null;
  12. }
  13. @Override
  14. public boolean postProcessAfterInstantiation (Object bean, String beanName) throws BeansException {
  15. if (beanName.equals( "exampleController")) {
  16. log.info( "----postProcessAfterInstantiation被执行:" + beanName);
  17. }
  18. return true;
  19. }
  20. @Override
  21. public PropertyValues postProcessProperties (PropertyValues pvs, Object bean, String beanName) throws BeansException {
  22. if (beanName.equals( "exampleController")) {
  23. log.info( "----postProcessProperties被执行:" + beanName);
  24. MutablePropertyValues mutablePropertyValues= new MutablePropertyValues();
  25. mutablePropertyValues.addPropertyValue( "creator", "fanfu");
  26. pvs=mutablePropertyValues;
  27. }
  28. return pvs;
  29. }
  30. @Override
  31. public Object postProcessBeforeInitialization (Object bean, String beanName) throws BeansException {
  32. if (beanName.equals( "exampleController")) {
  33. log.info( "----postProcessBeforeInitialization---" + beanName);
  34. //如果特定的bean实例化完成后,还未执行InitializingBean.afterPropertiesSet()方法之前,有一些其他操作,可以在这里实现
  35. }
  36. return bean;
  37. }
  38. @Override
  39. public Object postProcessAfterInitialization (Object bean, String beanName) throws BeansException {
  40. if (beanName.equals( "exampleController")) {
  41. log.info( "----postProcessAfterInitialization---" + beanName);
  42. //如果特定的bean实例化完成,InitializingBean.afterPropertiesSet()方法执行后,有一些其他操作,可以在这里实现
  43. }
  44. return bean;
  45. }
  46. }

4、编写单元测试验证InstantiationAwareBeanPostProcessor接口的功能特性;


   
  1. @Test
  2. public void test3 (){
  3. AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( "com.fanfu");
  4. ExampleController bean = context.getBean(ExampleController.class);
  5. Assert.isTrue( "fanfu".equals(bean.getCreator()), "属性替换失败");
  6. log.info( "----"+bean.getCreator());
  7. }

执行结果如下:

工作原理

注册时机

1、因为InstantiationAwareBeanPostProcessor接口继承于BeanPostProcessor接口,所以InstantiationAwareBeanPostProcessor接口的实现类的注册时机和BeanPostProcessor是一致的,因此很快就找到了InstantiationAwareBeanPostProcessor接口的实现类的注册入口,即org.springframework.context.support.AbstractApplicationContext#refresh--->registerBeanPostProcessors;

2、进入到AbstractApplicationContext#registerBeanPostProcessors方法内,会发现这段代码很干净,即依赖于PostProcessorRegistrationDelegate类的registerBeanPostProcessors()方法;


   
  1. protected void registerBeanPostProcessors (ConfigurableListableBeanFactory beanFactory) {
  2. PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
  3. }

3、进入到PostProcessorRegistrationDelegate类的registerBeanPostProcessors()方法又是另一番洞天:大致是可以分为四步,第一步,获取所有实现BeanPostProcessor接口的实现类的名称,实现方式示例中的MyBeanPostProcessors就在其中;

第二步,提前注册BeanPostProcessorChecker,主要用途是用于Bean创建过程中的日志信息打印记录;

第三步,就是把所有的BeanPostProcessor接口的实现类,按照是否实现PriorityOrdered接口、是否实现Ordered接口、其他,分为三组;

最后一步内容很长,不过很简单,即按第二步分成的三类,依次注册,具体的顺序是:1:实现PriorityOrdered接口BeanPostProcessor接口的实现类、2:实现实现Ordered接口BeanPostProcessor接口的实现类、3:其他的BeanPostProcessor接口的实现类,其中MyInstantiationAwareBeanPostProcessor属于第三类;

总结,InstantiationAwareBeanPostProcessor接口的实现类的注册,其本质是把接口的实现类注入到Spring容器的一个集合里存起来,具体的注册逻辑在PostProcessorRegistrationDelegate#registerBeanPostProcessors()。

执行时机

从实现方式的示例的单元测试执行结果可以看出,InstantiationAwareBeanPostProcessor接口继承于BeanPostProcessor的postProcessBeforeInitialization()和postProcessAfterInitialization()扩展点的执行时机是在Bean(ExampleController)实例化、属性注入完成后触发执行的,其具体的工作原理可以参考Springboot的扩展点之BeanPostProcessor,下面就InstantiationAwareBeanPostProcessor接口的另外三个扩展点的执行时机进行分析。

1、从实现方式示例中,可知InstantiationAwareBeanPostProcessor的第一个扩展点postProcessBeforeInstantiation()是在Eean实例化前触发执行的,所以寻找其执行时机的第一步就要找到Bean实例化的入口,通过debug很快找到了这个位置 ,AbstractApplicationContext#refresh--->finishBeanFactoryInitialization();

2、进入到finishBeanFactoryInitialization()方法,会发现ExampleController这个Bean的实例化是在

DefaultListableBeanFactory#preInstantiateSingletons方法;

3、这里实际被调用的是DefaultListableBeanFactory#preInstantiateSingletons方法,进入到这个方法内,又调用了AbstractBeanFactory#getBean(),从这才算真正Bean的获取或创建的入品口口。这里大致介绍一下getBean()的逻辑:当获取某一个bean时,先查询缓存确定是否存在,若存在,则直接返回,若不存在,则开始创建Bean,若Bean内依赖了另外一个Bean,则是上述过程的一个递归。

4、进入到AbstractBeanFactory#getBean方法,发现又调用了AbstractBeanFactory#doGetBean

-->DefaultSingletonBeanRegistry#getSingleton()

-->AbstractAutowireCapableBeanFactory#createBean();

这里需要注意一下,用到了lambda表达式,即把下面的函数式接口的具体实现作为DefaultSingletonBeanRegistry#getSingleton()的第二个形参singletonFactory

传进去,在DefaultSingletonBeanRegistry#getSingleton()内,执行到singletonFactory.getObject()时触发下面lambda表达式内的createBean();(lambda表达式的应用在Spirng的源码中应用很广泛,所以对这块不太熟悉的小伙伴可以着重研究一下)


   
  1. () -> {
  2. try {
  3. return createBean(beanName, mbd, args);
  4. }
  5. catch (BeansException ex) {
  6. destroySingleton(beanName);
  7. throw ex;
  8. }
  9. }

postProcessBeforeInstantiation()

5、源码分析本身并不难,难的是需要耐心,分析这么多了,实际上还未走到进入到InstantiationAwareBeanPostProcessor的扩展点,但是已经很接近了。进入到AbstractAutowireCapableBeanFactory#createBean()

--->AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation(),定睛一看第一个扩展点到了,具体且看下面的注释内容:


   
  1. protected Object resolveBeforeInstantiation (String beanName, RootBeanDefinition mbd) {
  2. Object bean = null;
  3. if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
  4. // 检查bean是不是合成的Bean,
  5. //InstantiationAwareBeanPostProcessor接口的实现类是否己注册
  6. if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
  7. //查询出目标Bean的Class实例
  8. Class<?> targetType = determineTargetType(beanName, mbd);
  9. if (targetType != null) {
  10. //开始执行第一个扩展方法postProcessBeforeInstantiation
  11. bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
  12. if (bean != null) {
  13. bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
  14. }
  15. }
  16. }
  17. mbd.beforeInstantiationResolved = (bean != null);
  18. }
  19. return bean;
  20. }

具体的扩展点postProcessBeforeInstantiation()的执行也是朴实无华:查询出所有接口的实现类,然后循环执行;只一需要注意的是扩展点处的返回值处理,这个时候目标Bean(ExampleController)未实例化,这时可以自定义一个Bean对象作为返回值把目标Bean替换掉,那么后续的postProcessBeforeInitialization扩展点还会触发执行,而其他扩展点将会跳过不再执行;什么意思呢?简单点理解就是正常情况下Spring管理目标Bean会一步一步的实例化、属性注入、初始化,但你想要实现点个性化的东西,Spring就把这个Bean实例化及以后的权利交给你了。


   
  1. protected Object applyBeanPostProcessorsBeforeInstantiation (Class<?> beanClass, String beanName) {
  2. for (BeanPostProcessor bp : getBeanPostProcessors()) {
  3. if (bp instanceof InstantiationAwareBeanPostProcessor) {
  4. InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
  5. Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
  6. if (result != null) {
  7. return result;
  8. }
  9. }
  10. }
  11. return null;
  12. }

postProcessAfterInstantiation()

6、从AbstractAutowireCapableBeanFactory#createBean()

--->AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation()完成第一个扩展点的执行,继续往下走就是AbstractAutowireCapableBeanFactory#doCreateBean了,要找到第二个、第三个扩展点都在这里面;

7、进入到AbstractAutowireCapableBeanFactory#doCreateBean方法,如下图,instanceWrapper.getWrappedInstance()完成了目标Bean(ExampleController)的示例化,但是属性exampleService还未注入;

继续往下走,调用populateBean(),完成对已实例化的目标Bean(ExampleController)的属性注入;如图进入到populateBean()就开始了第二个扩展点postProcessAfterInstantiation()方法的执行;这里要注意一下返回值的类型为布尔类型:如果返回true,则会继续执行第三个扩展点;如果返回fase,则第三个扩展点不会执行,直接return跳出了当前方法;

postProcessProperties()

还是在AbstractAutowireCapableBeanFactory#populateBean方法中,第二个扩展点执行过且返回值为true,接着往下就会执行到第三个扩展点postProcessProperties();

第三个扩展点要着重说一下,第三个扩展触发执行的时候Bean已经实例化,但是未完成属性注入,但是这里可以在里替换掉即将注入的属性。在实现方式的示例代码ExampleController类中,定义了一个String类型的属性creator,默认值为"gaox",在MyInstantiationAwareBeanPostProcessor#postProcessProperties中,把“gaox”替换为“fanfu”,再看单元测试的执行结果,默认值“gaox”被替换成了“fanfu”;

应用场景

其实了解了InstantiationAwareBeanPostProcessorr的功能特性、实现方式和工作原理,在遇到类似的业务需求的时候都可以应用这些扩展点,这里举一个平时开发中经用到但是应该没有注意到的一个Spring内部经典实现AutowiredAnnotationBeanPostProcessor。

通过的UML类图,可以看到AutowiredAnnotationBeanPostProcessor继承于InstantiationAwareBeanPostProcessorAdapter,而InstantiationAwareBeanPostProcessorAdapter又实现了SmartInstantiationAwareBeanPostProcessor接口,SmartInstantiationAwareBeanPostProcessor接口又继承了InstantiationAwareBeanPostProcessor。

AutowiredAnnotationBeanPostProcessor又实现了InstantiationAwareBeanPostProcessor的postProcessProperties();实现方式中示例代码ExampleController类的exampleService属性用@Autowired注解标记后,实际的注入实现逻辑就在AutowiredAnnotationBeanPostProcessor的postProcessProperties()内,有兴趣的小伙伴可以继续深入下去探寻一翻。


   
  1. @Override
  2. public PropertyValues postProcessProperties (PropertyValues pvs, Object bean, String beanName) {
  3. InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
  4. try {
  5. metadata.inject(bean, beanName, pvs);
  6. }
  7. catch (BeanCreationException ex) {
  8. throw ex;
  9. }
  10. catch (Throwable ex) {
  11. throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
  12. }
  13. return pvs;
  14. }


转载:https://blog.csdn.net/fox9916/article/details/128941464
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场