Springboot扩展点是Spring易扩展的一个重要体现,常见的开源框架的也经常基于这些扩展点与Springboot整合,熟悉这些扩展点的使用场景,有利于我们加深对spring容器的理解,也方便我们优雅的开发自己的中间件工具。
Springboot的扩展点可以大致分为两类,一类是对Spring容器的扩展点,一类是对Spring Bean的扩展 。Spring容器中Bean的生命周期内所有可扩展的点的调用顺序如下图。我们对其中主要的扩展点进行介绍。
1 容器扩展点
1.1 ApplicationContextInitializer
作用
Spring容器刷新之前,允许我们对ConfiurableApplicationContext的实例做一些扩展。
public class MyApplicationContextInitializer implements ApplicationContextInitializer {
@Override
public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
System.out.println("=====MyApplicationContextInitializer=====");
}
}
因为这时候spring容器还没被刷新,有以下三种方式让扩展生效:
方式1 启动类加入: springApplication.addInitializers(new MyApplicationContextInitializer())
方式2 配置文件配置: context.initializer.classes = com.dc.artemis.server.springbootExtend.MyApplicationContextInitializer
方式3 Spring SPI扩展: 在spring.factories中加入org.springframework.context.ApplicationContextInitializer= com.dc.artemis.server.springbootExtend.MyApplicationContextInitializer
1.2 BeanFactoryPostProcessor
调用时机
bean的定义信息都已经加载完毕,但是还没到实例化之前
refresh()的 this.invokeBeanFactoryPostProcessors(beanFactory)
代码示例
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
System.out.println("=====3 MyBeanFactoryPostProcessor postProcessBeanFactory=====");
}
}
应用
Spring 禁止循环依赖可以在这个扩展点设置
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
// 禁止循环依赖
((DefaultListableBeanFactory) configurableListableBeanFactory).setAllowCircularReferences(false);
}
1.3 BeanDefinitionRegistryPostProcessor
调用时机
同BeanFactoryPostProcessor,bean的定义信息都已经加载完毕,但是还没到实例化之前。
可以在这里动态注册自己的beanDefinition,加载classpath之外的bean。
代码示例
@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
System.out.println("=====1 MyBeanDefinitionRegistryPostProcessor postProcessBeanDefinitionRegistry=====");
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
System.out.println("=====2 MyBeanDefinitionRegistryPostProcessor postProcessBeanFactory=====");
}
}
与BeanFactoryPostProcessor的联系区别
BeanDefinitionRegistryPostProcessor 是 BeanFactoryPostProcessor的子接口。
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry var1) throws BeansException;
}
postProcessBeanDefinitionRegistry主要是为了注册bean,postProcessBeanFactory主要是bean注册后对bean进行修改
2 Bean扩展点
以DogService为例,说明bean的扩展点
@Service
@Slf4j
public class DogService {
public DogService(){
log.info("===========DogService-2 constructor");
}
}
2.1 BeanPostProcessor
调用时机
- postProcessBeforeInitialization bean初始化之前
- postProcessAfterInitialization bean初始化之后
代码示例
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
// 初始化bean之前
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof DogService){
System.out.println("===========DogService-6 BeanFactoryPostProcessor#postProcessBeforeInitialization");
}
return bean;
}
@Override
//初始化bean之后
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof DogService){
System.out.println("===========DogService-8 BeanFactoryPostProcessor#postProcessAfterInitialization");
}
return bean;
}
}
2.2 InstantiationAwareBeanPostProcessor
调用时机
- postProcessBeforeInitialization bean实例化之前
- postProcessAfterInitialization bean实例化之后
- postProcessProperties bean实例化之后,在属性注入时
- postProcessBeforeInstantiation bean初始化之前
- postProcessAfterInstantiation bean初始化之后
代码示例
@Component
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
//实例化bean之前
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if (beanClass == DogService.class){
System.out.println("===========DogService-1 InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation");
}
return null;
}
@Override
//实例化bean之后
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if (bean instanceof DogService){
System.out.println("===========DogService-3 InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation");
}
return true;
}
@Override
//实例化bean之后,在属性注入时阶段触发,@Autowired, @Resource等注解原理基于此方法实现
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
if (bean instanceof DogService){
System.out.println("===========DogService-4 InstantiationAwareBeanPostProcessor#postProcessProperties");
}
return null;
}
应用
@Autowired,@Resource等注解原理基于postProcessProperties方法实现
与BeanPostProcessor的联系区别
InstantiationAwareBeanPostProcessor 是BeanPostProcessor的子接口
BeanPostProcessor主要作用于bean初始化前后(此时bean已经实例化了)
InstantiationAwareBeanPostProcessor 新加了对bean实例化前后的扩展
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
@Nullable
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return true;
}
@Nullable
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
throws BeansException {
return null;
}
}
2.3 InitializingBean
调用时机
为bean提供了初始化方法的方式。触发时机在postProcessAfterInitialization之前
代码示例
@Service
@Slf4j
public class DogService implements InitializingBean{
@Override
public void afterPropertiesSet() throws Exception {
log.info("===========DogService-7 InitializingBean#afterPropertiesSet");
}
}
2.4 Aware
调用时机
Aware接口有 BeanNameAware,BeanFactoryAware, BeanClassLoaderAware等。
在bean实例化之后,初始化postProcessBeforeInitialization之前,拿到Spring容器中的XXX,这里以BeanNameAware为例,是拿到beanName。
代码示例
@Service
@Slf4j
public class DogService implements BeanNameAware {
@Override
public void setBeanName(String name) {
log.info("===========DogService-5 BeanNameAware#setBeanName" );
}
}
2.5 DisposableBean
调用时机
对象销毁时
代码示例
@Service
@Slf4j
public class DogService implements DisposableBean{
@Override
public void destroy() throws Exception {
log.info("===========DogService-9 DisposableBean#destroy");
}
}
2.6 bean扩展顺序
DogService的代码如下
@Service
@Slf4j
public class DogService implements DisposableBean, InitializingBean, BeanNameAware {
@Override
public void setBeanName(String name) {
log.info("===========DogService-5 BeanNameAware#setBeanName" );
}
public DogService(){
log.info("===========DogService-2 constructor");
}
@Override
public void afterPropertiesSet() throws Exception {
log.info("===========DogService-7 InitializingBean#afterPropertiesSet");
}
@Override
public void destroy() throws Exception {
log.info("===========DogService-9 DisposableBean#destroy");
}
}
运行结果
==DogService-1 InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
==DogService-2 constructor
==DogService-3 InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation
==DogService-4 InstantiationAwareBeanPostProcessor#postProcessProperties
==DogService-5 BeanNameAware#setBeanName
==DogService-6 BeanFactoryPostProcessor#postProcessBeforeInitialization
==DogService-7 InitializingBean#afterPropertiesSet
==DogService-8 BeanFactoryPostProcessor#postProcessAfterInitialization
==DogService-9 DisposableBean#destroy