Spring容器初始化扩展点
BeanFactoryPostProcessor
望文生义,从名字可以看出,它是BeanFactory的后处理器,先了解一下BeanFactory
BeanFactory的地位相当高,它是各种Bean的工厂,提供了一系列的getBean方法,常用的ApplicationContext就继承了它
BeanFactoryPostProcessor就是BeanFactory的后处理类,我们可以在BeanFactory初始化之后做一些操作,它提供了个postProcessBeanFactory()方法,这个方法被调用的时候,所有的Bean已经被创建,但是还没有被初始化,也就是说,通过它我们可以在初始化任何Bean之前,甚至读取并修改BeanDefinition(bean定义的元数据)
BeanDefinitionRegistryPostProcessor
这个接口继承了BeanFactoryPostProcessor,同样从名字上来看,这个接口是BeanDefinitionRegistry的后处理器,先介绍下
BeanDefinitionRegistry
BeanDefinitionRegistry是用来注册BeanDefinition的,BeanDefinition就是Bean的配置元数据或Bean的描述信息,比如Bean的属性值,构造方法的参数值等。上面的BeanFactory的BeanDefinition也是由它注册的
BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的扩展,允许在BeanFactoryPostProcessor被调用之前对BeanDefinition做一些操作,尤其是它可以注册BeanFactoryPostProcessor的BeanDefinition,它提供了一个方法postProcessBeanDefinitionRegistry(),这个方法被调用的时候,所有的BeanDefinition已经被加载了,但是所有的Bean还没被创建
注意:
所有的Bean生成都有个顺序:定义--->创建---->初始化
BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry()方法在Bean被定义但还没被创建的时候执行
BeanFactoryPostProcessor的postProcessBeanFactory()方法在Bean被创建但还没被初始化的时候执行
BeanPostProcessor
看名知,这个接口是Bean的后处理器,通过它我们可以在Bean初始化前后做一些操作,它提供了两个方法:
postProcessBeforInitialization():在Bean初始化之前做一些操作
postProcessAfterInitialization():在Bean初始化之后做一些操作
注意这两个方法都有两个参数,bean和beanName,并需要返回一个对象,所有的Bean在被初始化前后都会调用这两个方法,我们可以过滤出所关心的Bean对其进行一些操作,比如把某个Bean替换成代理对象
另外,在Bean中可以通过@PostConstruct注解来指定在被Construct之后紧接着做一些初始化操作,上面的postProcessAfterInitialization()方法是在@PostConstruct之后被调用的
InitializingBean
这个接口有一个afterPropertiesSet() 方法,该方法在所有的属性都被赋值后调用,属性被赋值是在初始化的时候做的,与BeanPostProcessor结合来看,afterPropertiesSet()方法将在postProcessBeforeInitialization()和postProcessAfterInitialization()之间被调用,@PostConstruct是紧跟初始化方法后的,所以@PostConstruct注解的方法在afterPropertiesSet()方法之前
栗子:
@Slf4j @Service public class ShouwhatService implements InitializingBean{ public ShouwhatService() { log.info("=====>construct"); } @PostConstruct public void postConstruct() { log.info("=====>postConstruct"); } @Override public void afterPropertiesSet() throws Exception { log.info("=====>afterPropertiesSet"); } } @Slf4j @Component public class ShouwhatBeanPostProcessor implements BeanPostProcessor { //使用某一个bean来看,否则,bean太多,太乱 String testBeanName = "shouwhatService"; @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if(testBeanName.equals(beanName)) { log.info("=====>postProcessBeforeInitialization"); } return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName); } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if(testBeanName.equals(beanName)) { log.info("=====>postProcessAfterInitialization"); } return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName); } } @Slf4j @Component public class ShouwhatBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { log.info("=====>postProcessBeanFactory"); } @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { log.info("=====>postProcessBeanDefinitionRegistry"); } }

从日志打印顺序分析:
BeanDefinition先注册,然后postProcessBeanDefinitionRegistry()方法被调用,在之后BeanFactory开始工作:装配BeanDefinition创建Bean(仅仅是创建),然后postProcessBeanFactory()方法被调用,
在BeanFactory创建Bean之后,准备初始化Bean,这个时候构造方法被调用,然后开始初始化,先调用postProcessBeforeInitialization()方法,初始化完成后,调用@PostConstruct注解的方法,然后调用InitializingBean的afterPropertiesSet()方法,最后调用postProcessAfterInitialization()方法
ApplicationContextAware
Spring提供了很多Aware接口,比如BeanFactoryAware、ApplicationContextAware、ResourceLoaderAware、ServletContextAware等等,这些接口一般都有一个setXXX()方法来设置对应的组件,如果我们的Bean实现了这些Aware的时候,就可以获取对应的资源
ApplicationContextUtils.java
/** * 保存applicationContext到静态变量<br/> * 解决一些静态类中使用bean的场景 * @author shouwhat * */ @Component public class ApplicationContextUtils implements ApplicationContextAware{ private static ApplicationContext applicationContextStatic; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { applicationContextStatic = applicationContext; } /** * 根据类型获取bean,如果一个接口有一个以上实现类,请使用 {@link #getBean(String, Class)} * @param <T> * @param clazz * @return */ public static <T> T getBean(Class<T> clazz) { return getBean(null, clazz); } /** * 根据类型和beanName获取bean * @param <T> * @param clazz * @return */ public static <T> T getBean(String beanName,Class<T> clazz) { if(applicationContextStatic == null) { throw new RuntimeException("ApplicationContenxtUtils init ApplicationContenxt fail---"); } if(StringUtils.isNotBlank(beanName)) { return applicationContextStatic.getBean(beanName,clazz); }else{ return applicationContextStatic.getBean(clazz); } } }
ApplicationListener
这跟Servlet中的监听器一样,采用了观察者模式,监听器往往都是监听某些事件源,
浙公网安备 33010602011771号