Spring之BeanPostProcessor

什么是BeanPostProcessor

BeanPostProcessor从本质上讲也是一个bean,它的实例化在普通bean之前,然后作用于普通bean。BeanPostProcessor可以作用于普通bean生命周期的以下几个阶段:

  • postProcessBeforeInitialization
  • postProcessMergedBeanDefinition
  • postProcessAfterInitialization
  • postProcessPropertyValues
  • postProcessBeforeInstantiation
  • postProcessAfterInstantiation

BeanPostProcessor实例化时机及排序问题

AbstractApplicationContext#refresh

具体实例化BeanPostProcessor的方法为registerBeanPostProcessors,该方法中有很多重复代码,大体可以分为查找、排序、注册三个阶段。具体排序规则如下:

  1. 实现了 PriorityOrdered 且未实现 MergedBeanDefinitionPostProcessor 接口的BeanPostProcessor
  2. 实现了 Ordered 且未实现 MergedBeanDefinitionPostProcessor 接口的BeanPostProcessor
  3. 未实现了 PriorityOrderedOrderedMergedBeanDefinitionPostProcessor 接口的BeanPostProcessor
  4. 实现了 PriorityOrderedMergedBeanDefinitionPostProcessor 接口的BeanPostProcessor
  5. 实现了OrderedMergedBeanDefinitionPostProcessor 接口的BeanPostProcessor
  6. 未实现了 PriorityOrderedOrdered 接口实现 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;

@Component
public 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;

@Component
public 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
@Component
public 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;

@Component
public 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;

@Component
public 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;

@Component
public 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;

@Component
public 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
  • 子类实现
    • InitDestroyAnnotationBeanPostProcessor$LifecycleElement
      • @PostConstruct标注的方法
    • ApplicationContextAwareProcessor#invokeAwareInterfaces
      • setEnvironment
      • setEmbeddedValueResolver
      • setResourceLoader
      • setApplicationEventPublisher
      • setMessageSource
      • setApplicationStartup
      • setApplicationContext
  • 方法之后
    • AbstractAutowireCapableBeanFactory#invokeInitMethods
      • 处理实现InitializingBean接口的bean
5.BeanPostProcessor#postProcessAfterInitialization

在这一阶段,最常见的作用就是动态代理。比如@EnableTransactionManagement注解会注入一个类型为 InfrastructureAdvisorAutoProxyCreator 的BeanPostProcessor,这个类的祖父类(AbstractAutoProxyCreator)的方法实现(postProcessAfterInitialization)就是对满足条件的bean进行动态代理。相关源码如下:

 PS : @EnableAspectJAutoProxy注解和@EnableAsync注解注入的BeanPostProcessor,也会在这一阶段对满足条件的bean进行动态代理

总结

BeanPostProcessor的作用很强大,但是也很危险,如果不加条件判断要处理的特定bean,所有的bean的都会受影响,所有的bean的都会受影响,所有的bean的都会受影响,重要的事情说三遍。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值