在 Spring 的 bean 裝載條件中,雖然 Spring 給我們提供了非常好用便捷的 Condition?相關注解,但是很多時候 Condition 相關注解并不滿足我們的需求,我需要更復雜的條件手動控制是否裝置 bean。這個時候我們就可以實現 Spring 為我們提供的幾個接口來實現手動 bean 的注入。
一、ApplicationContextAware 接口
在某些特殊的情況下,bean 需要實現某個功能,但該功能必須借助于 Spring 容器才能實現,此時就必須讓該 bean 先獲取 Spring 容器,然后借助于 Spring 容器實現該功能。為了讓 bean 獲取它所在的 Spring 容器,可以讓該 bean 實現 ApplicationContextAware 接口。ApplicationContextAware 通過它 Spring 容器會自動把上下文環境對象調用ApplicationContextAware 接口中的 setApplicationContext 方法。在 ApplicationContextAware 的實現類中,就可以通過這個上下文環境對象得到 Spring 容器中的 bean。
@Component
public class MyContextAware implements ApplicationContextAware {@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {System.out.println("SpringWebSocketContextAware");// 將 applicationContext 轉換為 ConfigurableApplicationContextConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) applicationContext;// 獲取 BeanFactoryDefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) configurableApplicationContext.getAutowireCapableBeanFactory();// 創建 bean 信息BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(Test.class);// 動態注冊 beandefaultListableBeanFactory.registerBeanDefinition("test", beanDefinitionBuilder.getBeanDefinition());}
}
?二、BeanDefinitionRegistryPostProcessor 接口
Spring 中并沒有具體去實現 postProcessBeanFactory 方法,是提供給想要實現BeanPostProcessor 的三方框架使用的。誰要使用誰就去實現。作用是在 BeanFactory 準備工作完成后做一些定制化的處理,一般結合 BeanPostProcessor 接口的實現類一起使用,注入一些重要資源。
@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {@Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {BeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Test.class).getBeanDefinition();registry.registerBeanDefinition("test", beanDefinition);}@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {BeanDefinitionRegistryPostProcessor.super.postProcessBeanFactory(beanFactory);}
}
三、ImportBeanDefinitionRegistrar 接口
在 spring 應用啟動過程,一些被 @Import 注解的類(這些類都實現了 ImportBeanDefinitionRegistrar 接口)會執行 ImportBeanDefinitionRegistrar 的registerBeanDefinitions 方法,然后生成 BeanDefinition 對象,并最終注冊到BeanDefinitionRegistry 中,為后續實例化 bean 做準備的。
@Component
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {@Overridepublic void registerBeanDefinitions(@NotNull AnnotationMetadata importingClassMetadata,@NotNull BeanDefinitionRegistry registry,@NotNull BeanNameGenerator importBeanNameGenerator) {this.registerBeanDefinitions(importingClassMetadata, registry);}@Overridepublic void registerBeanDefinitions(@NotNull AnnotationMetadata importingClassMetadata,BeanDefinitionRegistry registry) {BeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Test.class).getBeanDefinition();registry.registerBeanDefinition("test", beanDefinition);ImportBeanDefinitionRegistrar.super.registerBeanDefinitions(importingClassMetadata, registry);}
}
接口執行順序:ImportBeanDefinitionRegistrar ->?BeanDefinitionRegistryPostProcessor ->?ApplicationContextAware?