Springboot 启动扩展点详解

611 阅读4分钟

Springboot扩展点是Spring易扩展的一个重要体现,常见的开源框架的也经常基于这些扩展点与Springboot整合,熟悉这些扩展点的使用场景,有利于我们加深对spring容器的理解,也方便我们优雅的开发自己的中间件工具。

Springboot的扩展点可以大致分为两类,一类是对Spring容器的扩展点,一类是对Spring Bean的扩展 。Spring容器中Bean的生命周期内所有可扩展的点的调用顺序如下图。我们对其中主要的扩展点进行介绍。

image.png

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的联系区别
BeanDefinitionRegistryPostProcessorBeanFactoryPostProcessor的子接口。

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的联系区别
InstantiationAwareBeanPostProcessorBeanPostProcessor的子接口
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