我是靠谱客的博主 鲜艳耳机,最近开发中收集的这篇文章主要介绍SpringBoot 扩展性接口,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

1.可扩展的接口启动调用顺序图

org.springframework.beans.factory.xxx
org.springframework.boot.xxx
org.springframework.context.xxx
在这里插入图片描述

  1. ApplicationContextInitializer.initialize
  2. AbstractApplicationContext.refresh
  3. BeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry
  4. BeanDefinitionRegistryPostProcessor.postProcessBeanFactory
  5. InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation
  6. SmartInstantiationAwareBeanPostProcessor.determineCandidateConstructors
  7. MergedBeanDefinitionPostProcessor.postProcessorMergedBeanDefinition
  8. InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation
  9. SmartInstantiationAwareBeanPostProcessor.getEarlyBeanReference
  10. BeanFactoryAware.setBeanFactory
  11. InstantiationAwareBeanPostProcessor.postProcessPropertyValues
  12. ApplicationContextAwareProcessor.invokeAwareInterfaces
  13. BeanNameAware.setBeanName
  14. InstantiationAwareBeanPostProcessor.postProcessBeforeInitialization
  15. @PostConstruct
  16. InitiallzingBean.afterPropertiesSet
  17. InstantiationAwareBeanPostProcessor.postProcessAfterInitialization
  18. FactoryBean.getObject
  19. SmartInitilallzingSingleton.afterSingletonInstantiated
  20. CommondLineRunner.run
  21. DisposableBean.destry

2.ApplicationContextInitializer

org.springframework.context.ApplicationContextInitializer

这是整个spring容器在刷新之前初始化ConfigurableApplicationContext的回调接口,简单来说,就是在容器刷新之前调用此类的initialize方法。这个点允许被用户自己扩展。用户可以在整个spring容器还没被初始化之前做一些事情。

可以想到的场景可能为,在最开始激活一些配置,或者利用这时候class还没被类加载器加载的时机,进行动态字节码注入等操作。

public class TestApplicationContextInitializer implements ApplicationContextInitializer {      
    @Override      
    public void initialize(ConfigurableApplicationContext applicationContext) {      
        System.out.println("[ApplicationContextInitializer]");      
    }      
}  

因为这时候spring容器还没被初始化,所以想要自己的扩展的生效,有以下三种方式:

  • 在启动类中用springApplication.addInitializers(new TestApplicationContextInitializer())语句加入

  • 配置文件配置context.initializer.classes=com.example.demo.TestApplicationContextInitializer

  • Spring SPI扩展,在spring.factories中加入org.springframework.context.ApplicationContextInitializer=com.example.demo.TestApplicationContextInitializer

3.BeanDefinitionRegistryPostProcessor

org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor

这个接口在读取项目中的beanDefinition之后执行,提供一个补充的扩展点

使用场景:你可以在这里动态注册自己的beanDefinition,可以加载classpath之外的bean

public class TestBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {      
    @Override      
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {      
        System.out.println("[BeanDefinitionRegistryPostProcessor] postProcessBeanDefinitionRegistry");      
    }      
      
    @Override      
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {      
        System.out.println("[BeanDefinitionRegistryPostProcessor] postProcessBeanFactory");      
    }      
}   

4.BeanFactoryPostProcessor

org.springframework.beans.factory.config.BeanFactoryPostProcessor

这个接口是beanFactory的扩展接口,调用时机在spring在读取beanDefinition信息之后,实例化bean之前。

在这个时机,用户可以通过实现这个扩展接口来自行处理一些东西,比如修改已经注册的beanDefinition的元信息

public class TestBeanFactoryPostProcessor implements BeanFactoryPostProcessor {      
    @Override      
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {      
        System.out.println("[BeanFactoryPostProcessor]");      
    }      
}      

5.InstantiationAwareBeanPostProcessor

org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor

继承了BeanPostProcessor, 而BeanPostProcessor只在bean的初始化阶段进行扩展, 而InstantiationAwareBeanPostProcessor接口则在初始化阶段, 实例化阶段和属性注入阶段

public class TestInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {      
      
    @Override      
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {      
        System.out.println("[TestInstantiationAwareBeanPostProcessor] before initialization " + beanName);      
        return bean;      
    }      
      
    @Override      
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {      
        System.out.println("[TestInstantiationAwareBeanPostProcessor] after initialization " + beanName);      
        return bean;      
    }      
      
    @Override      
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {      
        System.out.println("[TestInstantiationAwareBeanPostProcessor] before instantiation " + beanName);      
        return null;      
    }      
      
    @Override      
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {      
        System.out.println("[TestInstantiationAwareBeanPostProcessor] after instantiation " + beanName);      
        return true;      
    }      
      
    @Override      
    public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {      
        System.out.println("[TestInstantiationAwareBeanPostProcessor] postProcessPropertyValues " + beanName);      
        return pvs;      
    }      
  • postProcessBeforeInstantiation: 实例化bean之前,相当于new这个bean之前
  • postProcessAfterInstantiation: 实例化bean之后, 相当与new这个bean之后
  • postProcessPropertyValues: bean 已经实例化以后, 在属性注入阶段触发, @Autowired和@Resource基于此方法
  • postProcessBeforeInitialization: 初始化bean之前, 相当于把bean注入spring上下文之前
  • postProcessAfterInitialization: 初始化bean之后, 相当于把bean注入spring上下文之后

写中间件和业务中,都能利用这个特性。比如对实现了某一类接口的bean在各个生命期间进行收集,或者对某个类型的bean进行统一的设值等等。

6.SmartInstantiationAwareBeanPostProcessor

org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor

public class TestSmartInstantiationAwareBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor {      
      
    @Override      
    public Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {      
        System.out.println("[TestSmartInstantiationAwareBeanPostProcessor] predictBeanType " + beanName);      
        return beanClass;      
    }      
      
    @Override      
    public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {      
        System.out.println("[TestSmartInstantiationAwareBeanPostProcessor] determineCandidateConstructors " + beanName);      
        return null;      
    }      
      
    @Override      
    public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {      
        System.out.println("[TestSmartInstantiationAwareBeanPostProcessor] getEarlyBeanReference " + beanName);      
        return bean;      
    }      
}
  • predictBeanType: 该触发点发生在postProcessBeforeInstantiation之前, 这个方法用于预测Bean的类型, 返回第一个预测成功的Class类型, 如果不能预测返回null。当你调用BeanFactory.getType(name)时当通过bean的名字无法得到bean类型信息时就调用该回调方法来决定类型信息。
  • determineCandidateConstructors: 该触发点发生在postProcessBeforeInstantiation之后, 用于确定bean的构造函数, 返回的是bean的所以构造函数列表, 可以通过此方法自定义选择对应的构造器来实例化bean
  • getEarlyBeanReference: 该触发点发生在postProcessAfterInstantiation之后, 当有循环依赖的场景,当bean实例化好之后,为了防止有循环依赖,会提前暴露回调方法,用于bean实例化的后置处理。这个方法就是在提前暴露的回调方法中触发。

7.BeanFactoryAware

org.springframework.beans.factory.BeanFactoryAware

发生在bean的实例化之后,注入属性之前,也就是Setter之前。这个类的扩展点方法为setBeanFactory,可以拿到BeanFactory这个属性。

public class TestBeanFactoryAware implements BeanFactoryAware {      
    @Override      
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {      
        System.out.println("[TestBeanFactoryAware] " + beanFactory.getBean(TestBeanFactoryAware.class).getClass().getSimpleName());      
    }      
} 

可以在bean实例化之后, 初始化之前, 拿到beanFactory, 然后对bean进行特殊化的定制, 或者将beanFactory拿到进行缓存, 日后使用。

8.ApplicationContextAwareProcessor

org.springframework.context.support.ApplicationContextAwareProcessor

	private void invokeAwareInterfaces(Object bean) {
		if (bean instanceof EnvironmentAware) {
			((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
		}
		if (bean instanceof EmbeddedValueResolverAware) {
			((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
		}
		if (bean instanceof ResourceLoaderAware) {
			((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
		}
		if (bean instanceof ApplicationEventPublisherAware) {
			((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
		}
		if (bean instanceof MessageSourceAware) {
			((MessageSourceAware) bean).setMessageSource(this.applicationContext);
		}
		if (bean instanceof ApplicationStartupAware) {
			((ApplicationStartupAware) bean).setApplicationStartup(this.applicationContext.getApplicationStartup());
		}
		if (bean instanceof ApplicationContextAware) {
			((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
		}
	}

6个扩展点: EnvironmentAware, EmbeddedValueResolverAware, ResourceLoaderAware, ApplicationEventPublisherAware, MessageSourceAware, ApplicationContextAware, ApplicationStartupAware

9.BeanNameAware

org.springframework.beans.factory.BeanNameAware

public class NormalBeanA implements BeanNameAware{      
    public NormalBeanA() {      
        System.out.println("NormalBean constructor");      
    }      
      
    @Override      
    public void setBeanName(String name) {      
        System.out.println("[BeanNameAware] " + name);      
    }      
}

触发点为bean的初始化之前, postProcessBeforeInitialization方法之前, 可以通过在初始化bean之前拿到spring容器中注册的的beanName, 修改beanName。

10.@PostConstruct

javax.annotation.PostConstruct

public class NormalBeanA {      
    public NormalBeanA() {      
        System.out.println("NormalBean constructor");      
    }      
      
    @PostConstruct      
    public void init(){      
        System.out.println("[PostConstruct] NormalBeanA");      
    }      
}

触发点是在postProcessBeforeInitialization之后,InitializingBean.afterPropertiesSet之前。

11.InitializingBean

org.springframework.beans.factory.InitializingBean

初始化bean, 在方法postProcessAfterInitialization之前实现。

public class NormalBeanA implements InitializingBean{      
    @Override      
    public void afterPropertiesSet() throws Exception {      
        System.out.println("[InitializingBean] NormalBeanA");      
    }      
}

进行系统启动的时候一些业务指标的初始化工作

12.FactoryBean

org.springframework.beans.factory.FactoryBean

工厂Bean, Spring提供了70多个实现, 隐藏了复杂的bean的细节, 给上层提供了便利

public class TestFactoryBean implements FactoryBean<TestFactoryBean.TestFactoryInnerBean> {      
      
    @Override      
    public TestFactoryBean.TestFactoryInnerBean getObject() throws Exception {      
        System.out.println("[FactoryBean] getObject");      
        return new TestFactoryBean.TestFactoryInnerBean();      
    }      
      
    @Override      
    public Class<?> getObjectType() {      
        return TestFactoryBean.TestFactoryInnerBean.class;      
    }      
      
    @Override      
    public boolean isSingleton() {      
        return true;      
    }      
      
    public static class TestFactoryInnerBean{      
      
    }      
}      

可以通过这个类, 实例化bean作为一个代理, 比如为该对象的所以方法做一个拦截, 输出一个日志信息。

13.SmartInitializingSingleton

org.springframework.beans.factory.SmartInitializingSingleton

  • afterSingletonsInstantiated: 在spring容器管理的所有单例对象(非懒加载对象)初始化完成之后调用的回调接口。在postProcessAfterInitialization之后执行。
public class TestSmartInitializingSingleton implements SmartInitializingSingleton {      
    @Override      
    public void afterSingletonsInstantiated() {      
        System.out.println("[TestSmartInitializingSingleton]");      
    }      
}

可以对于所有单例对象初始化后, 做出一些业务处理

14.CommandLineRunner

org.springframework.boot.CommandLineRunner

run方法在触发时机为整个项目启动完毕后,自动执行。如果有多个CommandLineRunner,可以利用@Order来进行排序。

public class TestCommandLineRunner implements CommandLineRunner {      
      
    @Override      
    public void run(String... args) throws Exception {      
        System.out.println("[TestCommandLineRunner]");      
    }      
}

15.DisposableBean

org.springframework.beans.factory.DisposableBean

  • destroy: 对象销毁时执行。
public class NormalBeanA implements DisposableBean {      
    @Override      
    public void destroy() throws Exception {      
        System.out.println("[DisposableBean] NormalBeanA");      
    }      
}

16.ApplicationListener

org.springframework.context.ApplicationListener

可以监控某个事件, spring内部有内置事件, 可以利用内置事件的监听器达到和前面一些触发点大致相同的事情。

  1. ContextRefreshedEvent: ApplicationContext 被初始化或刷新时,该事件被发布。这也可以在ConfigurableApplicationContext接口中使用 refresh()方法来发生。
  2. ContextStartedEvent: ConfigurableApplicationContext.started()启动ApplicationContext, 发布事件。
  3. ContextStoppedEvent: ConfigurableApplicationContext.stopped()停止ApplicationContext, 发布事件。
  4. ContextClosedEvent: ConfigurableApplicationContext.closed()关闭ApplicationContext, 发布事件。
  5. RequestHandledEvent: web-specific 事件, 告诉所有Bean Http 请求已经被服务。只能应用于使用DispatcherServlet的Web应用。当Spring处理用户请求结束后,系统会自动触发该事件。

最后

以上就是鲜艳耳机为你收集整理的SpringBoot 扩展性接口的全部内容,希望文章能够帮你解决SpringBoot 扩展性接口所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(39)

评论列表共有 0 条评论

立即
投稿
返回
顶部