ToB企服应用市场:ToB评测及商务社交产业平台

标题: 万字长文带你窥探Spring中所有的扩展点 [打印本页]

作者: 缠丝猫    时间: 2024-9-8 15:41
标题: 万字长文带你窥探Spring中所有的扩展点
写在前面

Spring的焦点思想就是容器,当容器refresh的时候,外部看上去风平浪静,其实内部则是一片惊涛骇浪,汪洋一片。Springboot更是封装了Spring,遵循约定大于配置,加上主动装配的机制。很多时候我们只要引用了一个依赖,几乎是零配置就能完成一个功能的装配。
由spring提供的、在容器或bean生命周期各个阶段、供spring框架回调使用的函数方法,即为扩展点。扩展点体现了Spring框架的灵活性、业务亲和性。使开辟人员可以在不修改spring源码的情况下,对容器和bean的行为、属性进行额外的管理。
想要把主动装配玩的转,就必须要相识spring对于bean的构造生命周期以及各个扩展接口,当然相识了bean的各个生命周期也能促进我们加深对spring的理解。业务代码也能公道利用这些扩展点写出更优雅的代码。
在网上搜索spring扩展点,发现很少有博文说的很全的,只有一些常用的扩展点的说明。所以在这篇文章里,我总结了几乎Spring & Springboot所有的扩展接口,各个扩展点的使用场景,并整理出一个bean在spring中从被加载到初始化到销毁的所有可扩展点的顺序调用图。
本文不讲原理,只将扩展点与使用方式讲清晰,特殊是调用顺序,原理可以移步IOC系列文章Bean的生命周期,后续会不停更新对应原理及源码解析。大家可以把这篇文章当成一个工具书,当忘了实行顺序时,大概忘了如何使用这个扩展方式时,可以再回过头来看看。

ApplicationContextInitializer

org.springframework.context.ApplicationContextInitializer
介绍

这是整个spring容器在刷新之前初始化ConfigurableApplicationContext的回调接口,简朴来说,就是在容器刷新refresh之前调用 此类的initialize方法。这个接口的主要目标是在 Spring 应用上下文初始化的早期阶段进行一些配置或调解,以便在上下文加载后可以使用这些配置。
此接口,Spring Framework自己没有提供任何的实现类,但在SpringBoot对它有较多的扩展实现。
使用场景

  1. public class EnvironmentInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
  2.     @Override
  3.     public void initialize(ConfigurableApplicationContext applicationContext) {
  4.         ConfigurableEnvironment environment = applicationContext.getEnvironment();
  5.         environment.setActiveProfiles("development");
  6.         System.out.println("配置文件设置为development");
  7.     }
  8. }
复制代码
  1. public class CustomBeanFactoryPostProcessorInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
  2.     @Override
  3.     public void initialize(ConfigurableApplicationContext applicationContext) {
  4.         applicationContext.addBeanFactoryPostProcessor(beanFactory -> {
  5.             // 添加自定义的 BeanFactoryPostProcessor
  6.             System.out.println("添加了自定义BeanFactory后处理器...");
  7.         });
  8.     }
  9. }
复制代码
  1. public class PropertySourceInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
  2.     @Override
  3.     public void initialize(ConfigurableApplicationContext applicationContext) {
  4.         MutablePropertySources propertySources = applicationContext.getEnvironment().getPropertySources();
  5.         propertySources.addFirst(new MapPropertySource("customPropertySource", Collections.singletonMap("customKey", "customValue")));
  6.         System.out.println("已添加自定义属性源");
  7.     }
  8. }
复制代码
Spring情况下添加扩展点

在Spring情况下自界说实现一个ApplicationContextInitializer让并且它生效的方式有三种:
  1. ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext();
  2. // Add initializer
  3. context.addApplicationListener(new TestApplicationContextInitializer());
  4. // Set config locations and refresh context
  5. context.setConfigLocation("classpath:applicationContext.xml");
  6. context.refresh();
  7. // Use the context
  8. // ...
  9. context.close();
复制代码
  1. [/code][list=1]
  2. [*]web.xml 文件配置
  3. [/list][code]<context-param>
  4.     <param-name>contextInitializerClasses</param-name>
  5.     <param-value>com.seven.springsrpingbootextentions.extentions.TestApplicationContextInitializer</param-value>
  6. </context-param>
复制代码
SpringBoot情况下添加扩展点

示例,展示了如何实现一个ApplicationContextInitializer来添加一个自界说的属性源:
  1. public class TestApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
  2.     @Override
  3.     public void initialize(ConfigurableApplicationContext applicationContext) {
  4.         MutablePropertySources propertySources = applicationContext.getEnvironment().getPropertySources();
  5.         
  6.         // 创建自定义的属性源
  7.         Map<String, Object> customProperties = new HashMap<>();
  8.         customProperties.put("custom.property", "custom value");
  9.         MapPropertySource customPropertySource = new MapPropertySource("customPropertySource", customProperties);
  10.         
  11.         // 将自定义属性源添加到应用程序上下文的属性源列表中
  12.         propertySources.addFirst(customPropertySource);
  13.     }
  14. }
复制代码
在SpringBoot中让它生效的方式也有三种:
  1. @SpringBootApplication
  2. public class MySpringExApplication {
  3.     public static void main(String[] args) {
  4.         SpringApplication application = new SpringApplication(MySpringExApplication.class);
  5.         application.addInitializers(new TestApplicationContextInitializer()); // 直接在SpringApplication中添加
  6.         application.run(args);
  7.     }
  8. }
复制代码
  1. # application.yml文件
  2. context:
  3.   initializer:
  4.     classes: com.seven.springsrpingbootextentions.extentions.TestApplicationContextInitializer
复制代码
  1. com.seven.springsrpingbootextentions.extentions.TestApplicationContextInitializer
复制代码
SpringBoot内置的ApplicationContextInitializer

BeanFactoryPostProcessor

org.springframework.beans.factory.config.BeanFactoryPostProcessor
介绍

这个接口是beanFactory的扩展接口,调用时机在spring在读取beanDefinition信息之后,实例化bean之前。虽然此时不能再注册beanDefinition,但是可以趁着bean没有实例化,可以修改 Spring 容器启动时修改其内部的 BeanDefinition。通过实现 BeanFactoryPostProcessor 接口,开辟者可以在 Bean 实例化之前修改 Bean 的界说元数据,比方Scope、依赖查找方式、初始化方法、修改属性值、添加额外的元数据等,进而影响初始化行为。
在应用步伐启动时,Spring容器会主动检测并调用所有实现了BeanFactoryPostProcessor接口的类的postProcessBeanFactory方法。开辟人员可以利用这个方法来实现自界说的逻辑,从而实现一些高级的自界说逻辑和功能扩展。此方法只调用一次,同时记住不要在这里做Bean的实例化
使用场景

  1. public class PropertyModifierBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
  2.     @Override
  3.     public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
  4.         BeanDefinition beanDefinition = beanFactory.getBeanDefinition("myBean");
  5.         MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
  6.         propertyValues.addPropertyValue("propertyName", "newValue");
  7.     }
  8. }
复制代码
  1. public class ConditionalBeanRegistrar implements BeanFactoryPostProcessor {
  2.     @Override
  3.     public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
  4.         if (someCondition()) {
  5.             BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(MyBean.class);
  6.             beanFactory.registerBeanDefinition("myConditionalBean", beanDefinitionBuilder.getBeanDefinition());
  7.         }
  8.     }
  9.     private boolean someCondition() {
  10.         // 自定义条件逻辑
  11.         return true;
  12.     }
  13. }
复制代码
  1. public class ScopeModifierBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
  2.     @Override
  3.     public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
  4.         BeanDefinition beanDefinition = beanFactory.getBeanDefinition("myBean");
  5.         beanDefinition.setScope(BeanDefinition.SCOPE_PROTOTYPE);
  6.     }
  7. }
复制代码
  1. public class CustomPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
  2.     @Override
  3.     protected void processProperties(ConfigurableListableBeanFactory beanFactory, Properties props)
  4.             throws BeansException {
  5.         super.processProperties(beanFactory, props);
  6.         // 自定义属性处理逻辑
  7.     }
  8. }
复制代码
其它使用场景:
BeanDefinitionRegistryPostProcessor

org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor
介绍

BeanDefinitionRegistryPostProcessor为容器级后置处置惩罚器。容器级的后置处置惩罚器会在Spring容器初始化后、刷新前实行一次,用于动态注册Bean到容器
通过 BeanFactoryPostProcessor 的子类 BeanDefinitionRegistryPostProcessor,可以注册一个你自己的BeanDefinition对象到容器中,等待容器内部依次调用进行对象实例化就能当bean用了。
BeanDefinitionRegistryPostProcessor用于在bean解析后实例化之前通过BeanDefinitionRegistry对BeanDefintion进行增删改查。
前文介绍的BeanFactoryPostProcessor是这个接口的父类,因此实现BeanDefinitionRegistryPostProcessor这个接口,也可以重写其父类。但实现了BeanDefinitionRegistryPostProcessor的postProcessBeanFactory方法会先实行,再实行实现了BeanFactoryPostProcessor的postProcessBeanFactory。详细看调用顺序图
使用场景

  1. public class BeanDefinitionModifier implements BeanDefinitionRegistryPostProcessor {
  2.     @Override
  3.     public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
  4.         System.out.println("在 postProcessBeanDefinitionRegistry 中修改现有的 BeanDefinition");
  5.         if (registry.containsBeanDefinition("myExistingBean")) {
  6.             BeanDefinition beanDefinition = registry.getBeanDefinition("myExistingBean");
  7.             MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
  8.             propertyValues.add("propertyName", "newValue");
  9.         }
  10.     }
  11.     @Override
  12.     public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
  13.         // 此方法可以留空或用于进一步处理
  14.     }
  15. }
复制代码
  1. public class ConditionalBeanRegistrar implements BeanDefinitionRegistryPostProcessor {
  2.     @Override
  3.     public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
  4.         System.out.println("在 postProcessBeanDefinitionRegistry 中根据条件注册 Bean");
  5.         if (someCondition()) {
  6.             AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder
  7.                     .genericBeanDefinition(ConditionalBean.class)
  8.                     .getBeanDefinition();
  9.             registry.registerBeanDefinition("conditionalBean", beanDefinition);
  10.         }
  11.     }
  12.     @Override
  13.     public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
  14.         // 此方法可以留空或用于进一步处理
  15.     }
  16.     private boolean someCondition() {
  17.         // 自定义条件逻辑
  18.         return true;
  19.     }
  20. }
复制代码
  1. public class CustomAnnotationBeanRegistrar implements BeanDefinitionRegistryPostProcessor {
  2.     @Override
  3.     public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
  4.         System.out.println("在 postProcessBeanDefinitionRegistry 中扫描并注册自定义注解的 Bean");
  5.         // 自定义扫描逻辑,假设找到一个类 MyAnnotatedBean
  6.         AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder
  7.                 .genericBeanDefinition(MyAnnotatedBean.class)
  8.                 .getBeanDefinition();
  9.         registry.registerBeanDefinition("myAnnotatedBean", beanDefinition);
  10.     }
  11.     @Override
  12.     public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
  13.         // 此方法可以留空或用于进一步处理
  14.     }
  15. }
复制代码
  1. @Configuration
  2. public class AppConfig {
  3.     @Bean
  4.     public static BeanDefinitionRegistryPostProcessor customBeanDefinitionRegistryPostProcessor() {
  5.         return new BeanDefinitionRegistryPostProcessor() {
  6.             @Override
  7.             public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
  8.                 System.out.println("在 postProcessBeanDefinitionRegistry 中根据条件注册缓存实现类");
  9.                 try {
  10.                     // 检查 Redis 依赖是否存在
  11.                     Class.forName("redis.clients.jedis.Jedis");
  12.                     System.out.println("检测到 Redis 依赖,注册 RedisCacheService");
  13.                     AbstractBeanDefinition redisCacheBeanDefinition = BeanDefinitionBuilder
  14.                             .genericBeanDefinition(RedisCacheService.class)
  15.                             .getBeanDefinition();
  16.                     registry.registerBeanDefinition("cacheService", redisCacheBeanDefinition);
  17.                 } catch (ClassNotFoundException e) {
  18.                     System.out.println("未检测到 Redis 依赖,注册 LocalCacheService");
  19.                     AbstractBeanDefinition localCacheBeanDefinition = BeanDefinitionBuilder
  20.                             .genericBeanDefinition(LocalCacheService.class)
  21.                             .getBeanDefinition();
  22.                     registry.registerBeanDefinition("cacheService", localCacheBeanDefinition);
  23.                 }
  24.             }
  25.             @Override
  26.             public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
  27.                 // 此方法可以留空或用于进一步处理
  28.             }
  29.         };
  30.     }
  31. }
复制代码
MapperScannerConfigurer 的主要功能是通过扫描指定的包路径,找到所有标注了 @Mapper 注解(或其他指定注解)的接口,并将这些接口注册为 Spring 的 BeanDefinition。这样,Spring 容器在启动时会主动创建这些 Mapper 接口的署理对象,并将其注入到需要的地方。
以下是 MapperScannerConfigurer 的焦点代码片段:
  1. // org.mybatis.spring.mapper.MapperScannerConfigurer#postProcessBeanDefinitionRegistry
  2. public class MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor, ApplicationContextAware {
  3.     private String basePackage;
  4.     private ApplicationContext applicationContext;
  5.     public void setBasePackage(String basePackage) {
  6.         this.basePackage = basePackage;
  7.     }
  8.     @Override
  9.     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
  10.         this.applicationContext = applicationContext;
  11.     }
  12.     @Override
  13.     public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
  14.         ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
  15.         //设置其资源加载器为当前的 ApplicationContext
  16.         scanner.setResourceLoader(this.applicationContext);
  17.         scanner.registerFilters();
  18.         //调用 scanner.scan(this.basePackage) 方法,扫描指定的包路径,找到所有符合条件的 Mapper 接口,并将它们注册为 Spring 的 BeanDefinition。
  19.         scanner.scan(this.basePackage);
  20.     }
  21.     @Override
  22.     public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
  23.         // 此方法可以留空或用于进一步处理
  24.     }
  25. }
复制代码
BeanPostProcessor

org.springframework.beans.factory.config.BeanPostProcessor
介绍

BeanPostProcessor 接口界说了两个基本的Bean初始化回调方法,在属性赋值前后实行。
使用场景

  1. @Component
  2. public class CustomBeanPostProcessor implements BeanPostProcessor {
  3.     @Override
  4.     public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
  5.         if (bean instanceof MyBean) {
  6.             System.out.println("bean初始化前: " + beanName);
  7.             ((MyBean) bean).setName("Modified Name Before Initialization");
  8.         }
  9.         return bean;
  10.     }
  11.     @Override
  12.     public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  13.         if (bean instanceof MyBean) {
  14.             System.out.println("bean初始化后: " + beanName);
  15.         }
  16.         return bean;
  17.     }
  18. }
  19. public class MyBean {
  20.     private String name;
  21.     public MyBean(String name) {
  22.         this.name = name;
  23.     }
  24.     public void setName(String name) {
  25.         this.name = name;
  26.     }
  27.     public void init() {
  28.         System.out.println("bean正在init: " + name);
  29.     }
  30.     @Override
  31.     public String toString() {
  32.         return "MyBean{name='" + name + "'}";
  33.     }
复制代码
  1. @Component
  2. public class ProxyBeanPostProcessor implements BeanPostProcessor {
  3.     @Override
  4.     public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  5.         if (bean instanceof MyBean) {
  6.             Enhancer enhancer = new Enhancer();
  7.             enhancer.setSuperclass(bean.getClass());
  8.             enhancer.setCallback(new MethodInterceptor() {
  9.                 @Override
  10.                 public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
  11.                     System.out.println("Before method: " + method.getName());
  12.                     Object result = proxy.invokeSuper(obj, args);
  13.                     System.out.println("After method: " + method.getName());
  14.                     return result;
  15.                 }
  16.             });
  17.             return enhancer.create();
  18.         }
  19.         return bean;
  20.     }
  21. }
复制代码
  1. @Component
  2. public class LoggingBeanPostProcessor implements BeanPostProcessor {
  3.     @Override
  4.     public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
  5.         System.out.println("开始初始化bean: " + beanName);
  6.         return bean;
  7.     }
  8.     @Override
  9.     public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  10.         System.out.println("初始化bean结束: " + beanName);
  11.         return bean;
  12.     }
  13. }
复制代码
  1. @Component
  2. public class AutowireBeanPostProcessor implements BeanPostProcessor {
  3.     @Override
  4.     public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
  5.         Field[] fields = bean.getClass().getDeclaredFields();
  6.         for (Field field : fields) {
  7.             if (field.isAnnotationPresent(AutowireCustom.class)) {
  8.                 field.setAccessible(true);
  9.                 try {
  10.                     field.set(bean, "Injected Value");
  11.                 } catch (IllegalAccessException e) {
  12.                     throw new BeansException("Failed to autowire field: " + field.getName(), e) {};
  13.                 }
  14.             }
  15.         }
  16.         return bean;
  17.     }
  18.     @Override
  19.     public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  20.         return bean;
  21.     }
  22. }
  23. @Retention(RetentionPolicy.RUNTIME)
  24. public @interface AutowireCustom {
  25. }
  26. public class MyBean {
  27.     @AutowireCustom
  28.     private String customField;
  29.     public MyBean() {
  30.     }
  31.     @Override
  32.     public String toString() {
  33.         return "MyBean{customField='" + customField + "'}";
  34.     }
  35. }
复制代码
InstantiationAwareBeanPostProcessor

org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor
介绍

该接口继承了BeanPostProcessor接口,由于InstantiationAwareBeanPostProcessor也属于Bean级的后置处置惩罚器,区别如下:
BeanPostProcess接口只在bean的初始化阶段进行扩展(注入spring上下文前后),而InstantiationAwareBeanPostProcessor接口在此底子上增加了3个方法,把可扩展的范围增加了实例化阶段和属性注入阶段。
该类主要的扩展点有以下6个方法,此中有两个是BeanPostProcessor的扩展,主要在bean生命周期的两大阶段:实例化阶段初始化阶段,下面一起进行说明,按调用顺序为:
留意:InstantiationAwareBeanPostProcessor和 BeanPostProcessor 是可以同时被实现的,并且也会同时生效,但是InstantiationAwareBeanPostProcessor的实行时机要稍早于BeanPostProcessor;详细看上面调用顺序图
InstantiationAwareBeanPostProcessor 提供了更细粒度的控制,可以在 Bean 的实例化和属性设置过程中插入自界说逻辑。无论是更换默认的实例化过程、控制依赖注入,还是修改属性值,InstantiationAwareBeanPostProcessor 都提供了强大的灵活性和可扩展性,使得开辟者可以在 Bean 的生命周期中进行更精致的控制。
使用场景

  1. @Component
  2. public class CustomInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
  3.     @Override
  4.     public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
  5.         if (beanClass == MyBean.class) {
  6.             System.out.println("实例化之前替换 Bean: " + beanName);
  7.             Enhancer enhancer = new Enhancer();
  8.             enhancer.setSuperclass(beanClass);
  9.             enhancer.setCallback(new MethodInterceptor() {
  10.                 @Override
  11.                 public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
  12.                     System.out.println("调用方法: " + method.getName());
  13.                     return proxy.invokeSuper(obj, args);
  14.                 }
  15.             });
  16.             return enhancer.create();
  17.         }
  18.         return null;
  19.     }
  20.    
  21.     @Override
  22.     public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  23.         System.out.println("初始化之后的 Bean: " + beanName);
  24.         return bean;
  25.     }
  26. }
复制代码
  1. @Component
  2. public class DependencyInjectionControlPostProcessor implements InstantiationAwareBeanPostProcessor {
  3.     @Override
  4.     public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
  5.         if (bean instanceof MyBean) {
  6.             System.out.println("实例化之后控制依赖注入: " + beanName);
  7.             return false; // 不进行默认的依赖注入
  8.         }
  9.         return true;
  10.     }
  11.     @Override
  12.     public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  13.         System.out.println("初始化之后的 Bean: " + beanName);
  14.         return bean;
  15.     }
  16. }
复制代码
  1. @Component
  2. public class PropertyModificationPostProcessor implements InstantiationAwareBeanPostProcessor {
  3.     @Override
  4.     public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
  5.         if (bean instanceof MyBean) {
  6.             System.out.println("设置属性值之前: " + beanName);
  7.             // 修改属性值的逻辑
  8.         }
  9.         return pvs;
  10.     }
  11.     @Override
  12.     public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  13.         System.out.println("初始化之后的 Bean: " + beanName);
  14.         return bean;
  15.     }
  16. }
复制代码
SmartInstantiationAwareBeanPostProcessor

org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor
介绍

SmartInstantiationAwareBeanPostProcessor 与其他扩展点最显着的不同,就是在现实的业务开辟场景中应用到的机会并不多,主要是在Spring内部应用。
该扩展接口有3个触发点方法:
留意:同InstantiationAwareBeanPostProcessor,由于SmartInstantiationAwareBeanPostProcessor 是 InstantiationAwareBeanPostProcessor的子类,因此也SmartInstantiationAwareBeanPostProcessor 也同样能扩展 InstantiationAwareBeanPostProcessor的所有方法。但是如果有两个类分别重写了 SmartInstantiationAwareBeanPostProcessor 和  InstantiationAwareBeanPostProcessor 的方法,那么重写 InstantiationAwareBeanPostProcessor 的类的方法 会先于 重写了 SmartInstantiationAwareBeanPostProcessor的类的方法(留意,这里说的是两者都有的方法)。
使用场景

  1. @Component
  2. public class CustomConstructorSelectionPostProcessor implements SmartInstantiationAwareBeanPostProcessor {
  3.     @Override
  4.     public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {
  5.         if (beanClass == MyBean.class) {
  6.             System.out.println("选择自定义构造函数: " + beanName);
  7.             try {
  8.                 return new Constructor<?>[] { beanClass.getConstructor(String.class) };
  9.             } catch (NoSuchMethodException e) {
  10.                 throw new BeansException("找不到指定的构造函数", e) {};
  11.             }
  12.         }
  13.         return null;
  14.     }
  15. }
  16. public class MyBean {
  17.     private String name;
  18.     public MyBean() {
  19.         this.name = "Default Name";
  20.     }
  21.     public MyBean(String name) {
  22.         this.name = name;
  23.     }
  24.     @Override
  25.     public String toString() {
  26.         return "MyBean{name='" + name + "'}";
  27.     }
  28. }
复制代码
  1. @Component
  2. public class EarlyBeanReferencePostProcessor implements SmartInstantiationAwareBeanPostProcessor {
  3.     @Override
  4.     public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
  5.         if (bean instanceof MyBean) {
  6.             System.out.println("获取早期 Bean 引用: " + beanName);
  7.             Enhancer enhancer = new Enhancer();
  8.             enhancer.setSuperclass(bean.getClass());
  9.             enhancer.setCallback(new MethodInterceptor() {
  10.                 @Override
  11.                 public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
  12.                     System.out.println("调用方法: " + method.getName());
  13.                     return proxy.invokeSuper(obj, args);
  14.                 }
  15.             });
  16.             return enhancer.create();
  17.         }
  18.         return bean;
  19.     }
  20. }
复制代码
  1. @Component
  2. public class BeanTypePredictionPostProcessor implements SmartInstantiationAwareBeanPostProcessor {
  3.     @Override
  4.     public Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {
  5.         if (beanClass == MyBean.class) {
  6.             System.out.println("预测 Bean 类型: " + beanName);
  7.             return MyBean.class;
  8.         }
  9.         return null;
  10.     }
  11. }
复制代码
MergedBeanDefinitionPostProcessor

org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor
介绍

MergedBeanDefinitionPostProcessor 继承自 BeanPostProcessor。调用的时机是,在实例化之后进行的调用,只要是收集bean上的属性的,比如收集标志了某些注解的字段大概方法,都可以基于MergedBeanDefinitionPostProcessor来进行扩展。
对于不同方式导入的Bean界说,如果存在重复对同一个Bean的界说,则会根据allowBeanDefinitionOverriding属性是否设置为true,判定是否允许Bean界说的覆盖,如果不允许,则抛出异常。而在Bean实例化之前,会进行BeanDefinition范例的归一化,即 mergeBeanFintion ,同一转换为RootBeanfintion进行后续处置惩罚。当然,这里的merge更多指代的是父子Bean界说的归并。
也用于收集bean上的注解,比如常见的@Value、@NacosValue、@Mapper等,再将收集好的数据缓存在injectionMetadataCache中,以便后续比如属性注入的时候使用。
该接口有两个扩展方法:
使用场景

  1. @Component
  2. public class CustomMergedBeanDefinitionPostProcessor implements MergedBeanDefinitionPostProcessor, BeanPostProcessor {
  3.     @Override
  4.     public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
  5.         if (beanType == MyBean.class) {
  6.             System.out.println("合并后的 Bean 定义信息, Bean 名称: " + beanName);
  7.             // 修改合并后的 Bean 定义信息
  8.             beanDefinition.getPropertyValues().add("name", "修改后的名称");
  9.         }
  10.     }
  11.     @Override
  12.     public void resetBeanDefinition(String beanName) {
  13.         System.out.println("重置 Bean 定义信息, Bean 名称: " + beanName);
  14.         // 实现重置逻辑
  15.     }
  16. }
  17. public class MyBean {
  18.     private String name;
  19.     public void setName(String name) {
  20.         this.name = name;
  21.     }
  22.     @Override
  23.     public String toString() {
  24.         return "MyBean{name='" + name + "'}";
  25.     }
  26. }
复制代码
  1. @Component
  2. public class CommonLogicMergedBeanDefinitionPostProcessor implements MergedBeanDefinitionPostProcessor, BeanPostProcessor {
  3.     @Override
  4.     public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
  5.         System.out.println("处理合并后的 Bean 定义信息, Bean 名称: " + beanName);
  6.         // 添加通用的自定义逻辑,例如给所有 Bean 添加某个属性
  7.         beanDefinition.getPropertyValues().add("commonProperty", "通用属性值");
  8.     }
  9.     @Override
  10.     public void resetBeanDefinition(String beanName) {
  11.         System.out.println("重置 Bean 定义信息, Bean 名称: " + beanName);
  12.         // 实现重置逻辑
  13.     }
  14. }
  15. public class MyBean {
  16.     private String name;
  17.     private String commonProperty;
  18.     public void setName(String name) {
  19.         this.name = name;
  20.     }
  21.     public void setCommonProperty(String commonProperty) {
  22.         this.commonProperty = commonProperty;
  23.     }
  24.     @Override
  25.     public String toString() {
  26.         return "MyBean{name='" + name + "', commonProperty='" + commonProperty + "'}";
  27.     }
  28. }
复制代码
  1. @Component
  2. public class ConditionalResetMergedBeanDefinitionPostProcessor implements MergedBeanDefinitionPostProcessor, BeanPostProcessor {
  3.     @Override
  4.     public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
  5.         System.out.println("处理合并后的 Bean 定义信息, Bean 名称: " + beanName);
  6.         // 这里可以根据条件决定是否修改 Bean 定义
  7.         if (beanName.equals("conditionalBean")) {
  8.             beanDefinition.getPropertyValues().add("name", "重置后的名称");
  9.         }
  10.     }
  11.     @Override
  12.     public void resetBeanDefinition(String beanName) {
  13.         System.out.println("重置 Bean 定义信息, Bean 名称: " + beanName);
  14.         // 这里可以实现条件性重置逻辑
  15.     }
  16. }
  17. public class ConditionalBean {
  18.     private String name;
  19.     public void setName(String name) {
  20.         this.name = name;
  21.     }
  22.     @Override
  23.     public String toString() {
  24.         return "ConditionalBean{name='" + name + "'}";
  25.     }
  26. }
复制代码
BeanNameAware

org.springframework.beans.factory.BeanNameAware
介绍

这个类是Aware扩展的一种,触发点在bean的初始化之前,也就是postProcessBeforeInitialization之前,这个类的触发点方法只有一个:setBeanName。
用于让 Bean 获得其在 Spring 容器中的名称。实现了 BeanNameAware 接口的 Bean 可以在初始化时获得自身的 Bean 名称,这在某些需要根据 Bean 名称进行逻辑处置惩罚的场景非常有用。
使用场景

  1. @Component
  2. public class LoggingBean implements BeanNameAware {
  3.     private String beanName;
  4.     @Override
  5.     public void setBeanName(String name) {
  6.         this.beanName = name;
  7.         System.out.println("设置 Bean 名称: " + name);
  8.     }
  9.     public void doSomething() {
  10.         System.out.println("正在执行某些操作, 当前 Bean 名称: " + beanName);
  11.     }
  12. }
  13. @Configuration
  14. @ComponentScan(basePackages = "com.seven")
  15. public class AppConfig {
  16.     public static void main(String[] args) {
  17.         ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
  18.         LoggingBean loggingBean = context.getBean(LoggingBean.class);
  19.         loggingBean.doSomething();
  20.     }
  21. }
复制代码
  1. @Component
  2. public class ConditionalLogicBean implements BeanNameAware {
  3.     private String beanName;
  4.     @Override
  5.     public void setBeanName(String name) {
  6.         this.beanName = name;
  7.         System.out.println("设置 Bean 名称: " + name);
  8.     }
  9.     public void performAction() {
  10.         if ("conditionalLogicBean".equals(beanName)) {
  11.             System.out.println("执行特定逻辑, 因为这是 conditionalLogicBean");
  12.         } else {
  13.             System.out.println("执行普通逻辑");
  14.         }
  15.     }
  16. }
  17. @Configuration
  18. @ComponentScan(basePackages = "com.seven")
  19. public class AppConfig {
  20.     public static void main(String[] args) {
  21.         ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
  22.         ConditionalLogicBean conditionalLogicBean = context.getBean(ConditionalLogicBean.class);
  23.         conditionalLogicBean.performAction();
  24.     }
  25. }
复制代码
  1. @Component("beanA")
  2. public class DynamicBeanA implements BeanNameAware {
  3.     private String beanName;
  4.     @Override
  5.     public void setBeanName(String name) {
  6.         this.beanName = name;
  7.         System.out.println("设置 Bean 名称: " + name);
  8.     }
  9.     public void execute() {
  10.         System.out.println("执行 Bean: " + beanName);
  11.     }
  12. }
  13. @Component("beanB")
  14. public class DynamicBeanB implements BeanNameAware {
  15.     private String beanName;
  16.     @Override
  17.     public void setBeanName(String name) {
  18.         this.beanName = name;
  19.         System.out.println("设置 Bean 名称: " + name);
  20.     }
  21.     public void execute() {
  22.         System.out.println("执行 Bean: " + beanName);
  23.     }
  24. }
  25. @Configuration
  26. @ComponentScan(basePackages = "com.seven")
  27. public class AppConfig {
  28.     public static void main(String[] args) {
  29.         ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
  30.         DynamicBeanA beanA = (DynamicBeanA) context.getBean("beanA");
  31.         DynamicBeanB beanB = (DynamicBeanB) context.getBean("beanB");
  32.         beanA.execute();
  33.         beanB.execute();
  34.     }
  35. }
复制代码
BeanClassLoaderAware

org.springframework.beans.factory.BeanClassLoaderAware
介绍

用于让一个 Bean 获取到加载它的 ClassLoader。实现这个接口的 Bean 会在其属性设置完成后、初始化方法调用之前被注入 ClassLoader。该接口界说了一个方法:
使用场景

  1. @Component
  2. public class DynamicClassLoader implements BeanClassLoaderAware {
  3.     private ClassLoader classLoader;
  4.     @Override
  5.     public void setBeanClassLoader(ClassLoader classLoader) {
  6.         this.classLoader = classLoader;
  7.         System.out.println("已设置类加载器");
  8.     }
  9.     public void loadClass(String className) {
  10.         try {
  11.             Class<?> clazz = classLoader.loadClass(className);
  12.             System.out.println("已加载类:" + clazz.getName());
  13.         } catch (ClassNotFoundException e) {
  14.             System.out.println("类未找到:" + className);
  15.         }
  16.     }
  17. }
  18. @SpringBootApplication
  19. public class AppConfig {
  20.     public static void main(String[] args) {
  21.         ConfigurableApplicationContext context = SpringApplication.run(AppConfig.class, args);
  22.         DynamicClassLoader dynamicClassLoader = context.getBean(DynamicClassLoader.class);
  23.         dynamicClassLoader.loadClass("java.util.ArrayList");
  24.         dynamicClassLoader.loadClass("不存在的类");
  25.     }
  26. }
复制代码
  1. @Component
  2. public class ClassAvailabilityChecker implements BeanClassLoaderAware {
  3.     private ClassLoader classLoader;
  4.     @Override
  5.     public void setBeanClassLoader(ClassLoader classLoader) {
  6.         this.classLoader = classLoader;
  7.         System.out.println("已设置类加载器");
  8.     }
  9.     public boolean isClassAvailable(String className) {
  10.         try {
  11.             Class<?> clazz = classLoader.loadClass(className);
  12.             System.out.println("类可用:" + clazz.getName());
  13.             return true;
  14.         } catch (ClassNotFoundException e) {
  15.             System.out.println("类不可用:" + className);
  16.             return false;
  17.         }
  18.     }
  19. }
  20. @SpringBootApplication
  21. public class AppConfig {
  22.     public static void main(String[] args) {
  23.         ConfigurableApplicationContext context = SpringApplication.run(AppConfig.class, args);
  24.         ClassAvailabilityChecker checker = context.getBean(ClassAvailabilityChecker.class);
  25.         checker.isClassAvailable("java.util.HashMap");
  26.         checker.isClassAvailable("不存在的类");
  27.     }
  28. }
复制代码
  1. @Component
  2. public class ResourceLoader implements BeanClassLoaderAware {
  3.     private ClassLoader classLoader;
  4.     @Override
  5.     public void setBeanClassLoader(ClassLoader classLoader) {
  6.         this.classLoader = classLoader;
  7.         System.out.println("已设置类加载器");
  8.     }
  9.     public void loadResource(String resourcePath) {
  10.         InputStream inputStream = classLoader.getResourceAsStream(resourcePath);
  11.         if (inputStream != null) {
  12.             System.out.println("资源已加载:" + resourcePath);
  13.         } else {
  14.             System.out.println("资源未找到:" + resourcePath);
  15.         }
  16.     }
  17. }
  18. @SpringBootApplication
  19. public class AppConfig {
  20.     public static void main(String[] args) {
  21.         ConfigurableApplicationContext context = SpringApplication.run(AppConfig.class, args);
  22.         ResourceLoader resourceLoader = context.getBean(ResourceLoader.class);
  23.         resourceLoader.loadResource("application.properties");
  24.         resourceLoader.loadResource("不存在的资源");
  25.     }
  26. }
复制代码
BeanFactoryAware

org.springframework.beans.factory.BeanFactoryAware
介绍

这个类只有一个触发点,发生在bean的实例化之后,注入属性之前,也就是Setter之前。这个类的扩展点方法为setBeanFactory,可以拿到BeanFactory这个属性,从而能够进行更复杂的 Bean 操作。比方,动态获取其他 Bean、检查 Bean 的状态等。
使用场景

  1. @Component
  2. public class DynamicBeanFetcher implements BeanFactoryAware {
  3.     private BeanFactory beanFactory;
  4.     @Override
  5.     public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
  6.         this.beanFactory = beanFactory;
  7.         System.out.println("注入 BeanFactory 实例");
  8.     }
  9.     public void fetchAndUseBean() {
  10.         MyBean myBean = beanFactory.getBean(MyBean.class);
  11.         System.out.println("获取到的 Bean 实例: " + myBean);
  12.     }
  13. }
  14. @Component
  15. public class MyBean {
  16.     @Override
  17.     public String toString() {
  18.         return "这是 MyBean 实例";
  19.     }
  20. }
  21. @Configuration
  22. @ComponentScan(basePackages = "com.seven")
  23. public class AppConfig {
  24.     public static void main(String[] args) {
  25.         ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
  26.         DynamicBeanFetcher fetcher = context.getBean(DynamicBeanFetcher.class);
  27.         fetcher.fetchAndUseBean();
  28.     }
  29. }
复制代码
  1. @Component
  2. public class BeanStateChecker implements BeanFactoryAware {
  3.     private BeanFactory beanFactory;
  4.     @Override
  5.     public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
  6.         this.beanFactory = beanFactory;
  7.         System.out.println("注入 BeanFactory 实例");
  8.     }
  9.     public void checkBeanState() {
  10.         boolean exists = beanFactory.containsBean("myBean");
  11.         System.out.println("MyBean 是否存在: " + exists);
  12.     }
  13. }
  14. @Component("myBean")
  15. public class MyBean {
  16.     @Override
  17.     public String toString() {
  18.         return "这是 MyBean 实例";
  19.     }
  20. }
  21. @Configuration
  22. @ComponentScan(basePackages = "com.seven")
  23. public class AppConfig {
  24.     public static void main(String[] args) {
  25.         ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
  26.         BeanStateChecker checker = context.getBean(BeanStateChecker.class);
  27.         checker.checkBeanState();
  28.     }
  29. }
复制代码
  1. @Component
  2. public class ComplexBeanInitializer implements BeanFactoryAware {
  3.     private BeanFactory beanFactory;
  4.     @Override
  5.     public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
  6.         this.beanFactory = beanFactory;
  7.         System.out.println("注入 BeanFactory 实例");
  8.     }
  9.     public void initializeComplexBean() {
  10.         MyBean myBean = beanFactory.getBean(MyBean.class);
  11.         System.out.println("初始化复杂 Bean, 获取到的 MyBean 实例: " + myBean);
  12.         // 在这里可以执行复杂的初始化逻辑
  13.     }
  14. }
  15. @Component
  16. public class MyBean {
  17.     @Override
  18.     public String toString() {
  19.         return "这是 MyBean 实例";
  20.     }
  21. }
  22. @Configuration
  23. @ComponentScan(basePackages = "com.seven")
  24. public class AppConfig {
  25.     public static void main(String[] args) {
  26.         ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
  27.         ComplexBeanInitializer initializer = context.getBean(ComplexBeanInitializer.class);
  28.         initializer.initializeComplexBean();
  29.     }
  30. }
复制代码
ApplicationContextAwareProcessor

org.springframework.context.support.ApplicationContextAwareProcessor
介绍

该类本身并没有扩展点,而是 BeanPostProcessor 扩展接口的详细实现,但是该类内部却有6个扩展点可供实现 ,这些扩展点的触发时机在bean实例化之后,初始化之前。
可以看到,该类用于实行各种驱动接口,在bean实例化之后,属性添补之后。其内部有6个扩展点可供实现,这几个接口都是Spring预留的重点扩展实现,与Spring的 Bean的生命周期 密切相干,以下按照扩展点调用顺序介绍:
使用场景

  1. @Component
  2. public class DynamicBeanFetcher implements ApplicationContextAware {
  3.     private ApplicationContext applicationContext;
  4.     @Override
  5.     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
  6.         this.applicationContext = applicationContext;
  7.         System.out.println("注入 ApplicationContext 实例");
  8.     }
  9.     public void fetchAndUseBean() {
  10.         MyBean myBean = applicationContext.getBean(MyBean.class);
  11.         System.out.println("获取到的 Bean 实例: " + myBean);
  12.     }
  13. }
  14. @Component
  15. public class MyBean {
  16.     @Override
  17.     public String toString() {
  18.         return "这是 MyBean 实例";
  19.     }
  20. }
  21. @Configuration
  22. @ComponentScan(basePackages = "com.seven")
  23. public class AppConfig {
  24.     public static void main(String[] args) {
  25.         ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
  26.         DynamicBeanFetcher fetcher = context.getBean(DynamicBeanFetcher.class);
  27.         fetcher.fetchAndUseBean();
  28.     }
  29. }
复制代码
  1. @Component
  2. public class EventPublisherBean implements ApplicationContextAware, ApplicationEventPublisherAware {
  3.     private ApplicationContext applicationContext;
  4.     private ApplicationEventPublisher eventPublisher;
  5.     @Override
  6.     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
  7.         this.applicationContext = applicationContext;
  8.         System.out.println("注入 ApplicationContext 实例");
  9.     }
  10.     @Override
  11.     public void setApplicationEventPublisher(ApplicationEventPublisher eventPublisher) {
  12.         this.eventPublisher = eventPublisher;
  13.     }
  14.     public void publishCustomEvent(String message) {
  15.         CustomEvent customEvent = new CustomEvent(this, message);
  16.         eventPublisher.publishEvent(customEvent);
  17.         System.out.println("发布自定义事件: " + message);
  18.     }
  19. }
  20. public class CustomEvent extends ApplicationEvent {
  21.     private String message;
  22.     public CustomEvent(Object source, String message) {
  23.         super(source);
  24.         this.message = message;
  25.     }
  26.     public String getMessage() {
  27.         return message;
  28.     }
  29. }
  30. @Component
  31. public class CustomEventListener {
  32.     @EventListener
  33.     public void handleCustomEvent(CustomEvent event) {
  34.         System.out.println("接收到自定义事件: " + event.getMessage());
  35.     }
  36. }
  37. @Configuration
  38. @ComponentScan(basePackages = "com.seven")
  39. public class AppConfig {
  40.     public static void main(String[] args) {
  41.         ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
  42.         EventPublisherBean publisher = context.getBean(EventPublisherBean.class);
  43.         publisher.publishCustomEvent("这是一个自定义事件消息");
  44.     }
  45. }
复制代码
  1. @Component
  2. public class EnvironmentAwareBean implements ApplicationContextAware {
  3.     private ApplicationContext applicationContext;
  4.     @Override
  5.     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
  6.         this.applicationContext = applicationContext;
  7.         System.out.println("注入 ApplicationContext 实例");
  8.     }
  9.     public void printEnvironmentProperty() {
  10.         Environment environment = applicationContext.getEnvironment();
  11.         String propertyValue = environment.getProperty("example.property");
  12.         System.out.println("读取到的环境属性值: " + propertyValue);
  13.     }
  14. }
  15. @Configuration
  16. @ComponentScan(basePackages = "com.seven")
  17. @PropertySource("classpath:application.properties")
  18. public class AppConfig {
  19.     public static void main(String[] args) {
  20.         ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
  21.         EnvironmentAwareBean environmentAwareBean = context.getBean(EnvironmentAwareBean.class);
  22.         environmentAwareBean.printEnvironmentProperty();
  23.     }
  24. }
复制代码
@PostConstruct

javax.annotation.PostConstruct
介绍

可以看出来其本身不是Spring界说的注解,但是Spring提供了详细的实现。这个并不算一个扩展点,其实就是一个标注。其作用是在bean的初始化阶段,如果对一个方法标注了@PostConstruct,会先调用这个方法。这里重点是要关注下这个标准的触发点,这个触发点是在postProcessBeforeInitialization之后,InitializingBean.afterPropertiesSet之前。
留意:
使用场景

使用场景与 InitializingBean 类似,详细看下文
InitializingBean

org.springframework.beans.factory.InitializingBean
介绍

这个类,顾名思义,也是用来初始化bean的。InitializingBean接口为bean提供了初始化方法的方式,它只在bean实例化、属性注入后的提供了一个扩展点afterPropertiesSet方法,凡是继承该接口的类,在初始前、属性赋值后,都会实行该方法。这个扩展点的触发时机在postProcessAfterInitialization之前。

留意:
使用场景

  1. public class NormalBeanA implements InitializingBean{
  2.     @Overrideimport org.springframework.beans.factory.InitializingBean;
  3. import org.springframework.stereotype.Component;
  4. @Component
  5. public class ResourceInitializer implements InitializingBean {
  6.     @Override
  7.     public void afterPropertiesSet() {
  8.         // 模拟资源初始化
  9.         System.out.println("资源初始化:建立数据库连接");
  10.     }
  11.     public void performAction() {
  12.         System.out.println("资源使用:执行数据库操作");
  13.     }
  14. }
  15.    
  16. @Configuration
  17. @ComponentScan(basePackages = "com.seven")
  18. public class AppConfig {
  19.     public static void main(String[] args) {
  20.         ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
  21.         ResourceInitializer initializer = context.getBean(ResourceInitializer.class);
  22.         initializer.performAction();
  23.     }
  24. }
复制代码
  1. @Component
  2. public class InitialValueSetter implements InitializingBean {
  3.     private String initialValue;
  4.     @Override
  5.     public void afterPropertiesSet() {
  6.         initialValue = "默认值";
  7.         System.out.println("设置初始值:" + initialValue);
  8.     }
  9.     public void printValue() {
  10.         System.out.println("当前值:" + initialValue);
  11.     }
  12. }
  13. @Configuration
  14. @ComponentScan(basePackages = "com.seven")
  15. public class AppConfig {
  16.     public static void main(String[] args) {
  17.         ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
  18.         InitialValueSetter valueSetter = context.getBean(InitialValueSetter.class);
  19.         valueSetter.printValue();
  20.     }
  21. }
复制代码
  1. @Component
  2. public class ConfigLoader implements InitializingBean {
  3.     private String configValue;
  4.     @Override
  5.     public void afterPropertiesSet() {
  6.         // 模拟配置加载
  7.         configValue = "配置值";
  8.         System.out.println("加载配置:" + configValue);
  9.     }
  10.     public void printConfig() {
  11.         System.out.println("当前配置:" + configValue);
  12.     }
  13. }
  14. @Configuration
  15. @ComponentScan(basePackages = "com.seven")
  16. public class AppConfig {
  17.     public static void main(String[] args) {
  18.         ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
  19.         ConfigLoader configLoader = context.getBean(ConfigLoader.class);
  20.         configLoader.printConfig();
  21.     }
  22. }
复制代码
SmartInitializingSingleton

org.springframework.beans.factory.SmartInitializingSingleton
介绍

这个接口中只有一个方法afterSingletonsInstantiated,其作用是是 在spring容器管理的所有单例对象(非懒加载对象)初始化完成之后调用的回调接口。其触发时机为postProcessAfterInitialization之后。
留意:
使用场景

  1. @Component
  2. public class GlobalInitializer implements SmartInitializingSingleton {
  3.     @Override
  4.     public void afterSingletonsInstantiated() {
  5.         // 模拟全局初始化操作
  6.         System.out.println("全局初始化操作:启动全局调度任务");
  7.     }
  8. }
复制代码
FactoryBean

org.springframework.beans.factory.FactoryBean
介绍

一般情况下,Spring通过反射机制利用bean的class属性指定支线类去实例化bean,在某些情况下,实例化Bean过程比较复杂,如果按照传统的方式,则需要在bean中提供大量的配置信息。Spring为此提供了一个org.springframework.bean.factory.FactoryBean的工厂类接口,用户可以通过实现该接口定制实例化Bean的逻辑。FactoryBean接口对于Spring框架来说占据重要的职位,Spring自身就提供了70多个FactoryBean的实现。它们隐藏了实例化一些复杂bean的细节,给上层应用带来了便利。
触发点:比方其他框架技能与Spring集成的时候,如mybatis与Spring的集成,mybatis是通过SqlSessionFactory创建出Sqlsession来实行sql的,那么Service层在调用Dao层的接口来实行数据库操作时肯定得持有SqlSessionFactory,那么问题来了:Spring容器怎么才气持有SqlSessionFactory呢?答案就是SqlSessionFactoryBean,它实现了FactoryBean接口。
FactoryBean 与 BeanFactory 的区别
使用场景

  1. class ComplexObject {
  2.     private String name;
  3.     private int value;
  4.     public ComplexObject(String name, int value) {
  5.         this.name = name;
  6.         this.value = value;
  7.     }
  8.     @Override
  9.     public String toString() {
  10.         return "ComplexObject{name='" + name + "', value=" + value + "}";
  11.     }
  12. }
  13. @Component
  14. public class ComplexObjectFactoryBean implements FactoryBean<ComplexObject> {
  15.     @Override
  16.     public ComplexObject getObject() {
  17.         // 创建复杂对象
  18.         ComplexObject complexObject = new ComplexObject("复杂对象", 42);
  19.         System.out.println("创建复杂对象:" + complexObject);
  20.         return complexObject;
  21.     }
  22.     @Override
  23.     public Class<?> getObjectType() {
  24.         return ComplexObject.class;
  25.     }
  26.     @Override
  27.     public boolean isSingleton() {
  28.         return true;
  29.     }
  30. }
  31. @Configuration
  32. @ComponentScan(basePackages = "com.seven")
  33. public class AppConfig {
  34.     public static void main(String[] args) {
  35.         ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
  36.         ComplexObject complexObject = context.getBean(ComplexObject.class);
  37.         System.out.println("获取复杂对象:" + complexObject);
  38.     }
  39. }
复制代码
  1. interface Service {
  2.     void execute();
  3. }
  4. class ServiceImplA implements Service {
  5.     @Override
  6.     public void execute() {
  7.         System.out.println("执行服务实现A");
  8.     }
  9. }
  10. class ServiceImplB implements Service {
  11.     @Override
  12.     public void execute() {
  13.         System.out.println("执行服务实现B");
  14.     }
  15. }
  16. @Component
  17. public class DynamicServiceFactoryBean implements FactoryBean<Service> {
  18.     private boolean useServiceA = true; // 可以通过配置或条件动态设置
  19.     @Override
  20.     public Service getObject() {
  21.         if (useServiceA) {
  22.             System.out.println("创建服务实现A");
  23.             return new ServiceImplA();
  24.         } else {
  25.             System.out.println("创建服务实现B");
  26.             return new ServiceImplB();
  27.         }
  28.     }
  29.     @Override
  30.     public Class<?> getObjectType() {
  31.         return Service.class;
  32.     }
  33.     @Override
  34.     public boolean isSingleton() {
  35.         return true;
  36.     }
  37. }
  38. @Configuration
  39. @ComponentScan(basePackages = "com.seven")
  40. public class AppConfig {
  41.     public static void main(String[] args) {
  42.         ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
  43.         Service service = context.getBean(Service.class);
  44.         service.execute();
  45.     }
  46. }
复制代码
  1. class LazyObject {
  2.     public LazyObject() {
  3.         System.out.println("懒对象被创建");
  4.     }
  5.     public void doSomething() {
  6.         System.out.println("懒对象执行操作");
  7.     }
  8. }
  9. @Component
  10. public class LazyObjectFactoryBean implements FactoryBean<LazyObject> {
  11.     @Override
  12.     public LazyObject getObject() {
  13.         System.out.println("创建懒对象实例");
  14.         return new LazyObject();
  15.     }
  16.     @Override
  17.     public Class<?> getObjectType() {
  18.         return LazyObject.class;
  19.     }
  20.     @Override
  21.     public boolean isSingleton() {
  22.         return true;
  23.     }
  24. }
  25. @Configuration
  26. @ComponentScan(basePackages = "com.seven")
  27. public class AppConfig {
  28.     public static void main(String[] args) {
  29.         ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
  30.         System.out.println("获取懒对象实例前");
  31.         LazyObject lazyObject = context.getBean(LazyObject.class);
  32.         System.out.println("获取懒对象实例后");
  33.         lazyObject.doSomething();
  34.     }
  35. }
复制代码
CommandLineRunner和ApplicationRunner

org.springframework.boot.CommandLineRunner
介绍

这两个是Springboot中新增的扩展点,之所以将这两个扩展点放在一起,是由于它两个功能特性高度相似,不同的只是名字、扩展方法形参数范例、实行先后的一些小的不同。
这两个接口触发时机为整个项目启动完毕后,主动实行。如果有多个CommandLineRunner,可以利用@Order来进行排序。
留意:
使用场景

  1. @Component
  2. public class DataInitializer implements CommandLineRunner {
  3.     @Override
  4.     public void run(String... args) {
  5.         System.out.println("初始化数据:插入初始数据");
  6.         // 模拟插入初始数据
  7.         insertInitialData();
  8.     }
  9.     private void insertInitialData() {
  10.         System.out.println("插入数据:用户表初始数据");
  11.     }
  12. }
复制代码
  1. @Component
  2. public class TaskExecutor implements CommandLineRunner {
  3.     @Override
  4.     public void run(String... args) {
  5.         System.out.println("启动后执行任务:发送启动通知");
  6.         // 模拟发送启动通知
  7.         sendStartupNotification();
  8.     }
  9.     private void sendStartupNotification() {
  10.         System.out.println("通知:应用已启动");
  11.     }
  12. }
复制代码
  1. @Component
  2. public class CommandLineArgsProcessor implements CommandLineRunner {
  3.     @Override
  4.     public void run(String... args) {
  5.         System.out.println("处理命令行参数:");
  6.         for (String arg : args) {
  7.             System.out.println("参数:" + arg);
  8.         }
  9.     }
  10. }
  11. @SpringBootApplication
  12. public class AppConfig {
  13.     public static void main(String[] args) {
  14.         SpringApplication.run(AppConfig.class, new String[]{"参数1", "参数2", "参数3"});
  15.     }
  16. }
复制代码
ApplicationListener 和 ApplicationContextInitializer

org.springframework.context.ApplicationListener
介绍

准确的说,这个应该不算spring&springboot当中的一个扩展点,ApplicationListener可以监听某个事故的event,触发时机可以穿插在业务方法实行过程中,用户可以自界说某个业务事故。但是spring内部也有一些内置事故,这种事故,可以穿插在启动调用中。我们也可以利用这个特性,来自己做一些内置事故的监听器来达到和前面一些触发点大致相同的事变。
接下来罗列下spring主要的内置事故:
使用场景

  1. // 定义自定义事件
  2. class CustomEvent extends ApplicationEvent {
  3.     private final String message;
  4.     public CustomEvent(Object source, String message) {
  5.         super(source);
  6.         this.message = message;
  7.     }
  8.     public String getMessage() {
  9.         return message;
  10.     }
  11. }
  12. // 监听自定义事件
  13. @Component
  14. public class CustomEventListener implements ApplicationListener<CustomEvent> {
  15.     @Override
  16.     public void onApplicationEvent(CustomEvent event) {
  17.         System.out.println("监听到自定义事件:处理事件");
  18.         handleCustomEvent(event);
  19.     }
  20.     private void handleCustomEvent(CustomEvent event) {
  21.         System.out.println("处理自定义事件:" + event.getMessage());
  22.     }
  23. }
  24. @Component
  25. public class EventPublisher implements ApplicationEventPublisherAware {
  26.    
  27.     private ApplicationEventPublisher eventPublisher;
  28.     @Override
  29.     public void setApplicationEventPublisher(ApplicationEventPublisher eventPublisher) {
  30.         this.eventPublisher = eventPublisher;
  31.     }
  32.     public void publishCustomEvent(final String message) {
  33.         System.out.println("发布自定义事件:" + message);
  34.         CustomEvent customEvent = new CustomEvent(this, message);
  35.         eventPublisher.publishEvent(customEvent);
  36.     }
  37. }
  38. @SpringBootApplication
  39. public class AppConfig {
  40.     public static void main(String[] args) {
  41.         ConfigurableApplicationContext context = SpringApplication.run(AppConfig.class, args);
  42.         EventPublisher publisher = context.getBean(EventPublisher.class);
  43.         publisher.publishCustomEvent("这是自定义事件的消息");
  44.     }
  45. }
复制代码
@PreDestroy

javax.annotation.PreDestroy
介绍

@PreDestroy 与@PostConstruct一样,是 Java EE 中的一个注解,用于在 Spring 容器销毁 Bean 之前实行特定的方法。这个注解通常用于开释资源、关闭连接、清算缓存等操作。与 @PostConstruct 类似,@PreDestroy 注解的方法会在 Bean 被销毁之前被调用。
使用场景

使用场景与 DisposableBean 类似,详细看下文。
DisposableBean

org.springframework.beans.factory.DisposableBean
介绍

这个扩展点也只有一个方法:destroy(),其触发时机为当此对象销毁、Spring容器关闭时,会主动实行这个方法。比如说运行applicationContext.registerShutdownHook时,就会触发这个方法。这个扩展点基本上用不到
留意:
使用场景

  1. @Component
  2. public class DatabaseConnectionManager implements DisposableBean {
  3.     @Override
  4.     public void destroy() {
  5.         System.out.println("释放数据库连接:关闭连接");
  6.         // 模拟关闭数据库连接
  7.         closeConnection();
  8.     }
  9.     private void closeConnection() {
  10.         System.out.println("数据库连接已关闭");
  11.     }
  12. }
复制代码
总结

我们从这些spring&springboot的扩展点当中,大致可以窥视到整个bean的生命周期。在业务开辟大概写中间件业务的时候,可以公道利用spring提供给我们的扩展点,在spring启动的各个阶段内做一些事变。以达到自界说初始化的目标。
本人也在持续学习中,因此此篇总结如果有错误大概疏漏的地方,恳请评论或接洽我进行指正,本文将持续迭代中~
关于作者

来自一线步伐员Seven的探索与实践,持续学习迭代中~
本文已收录于我的个人博客:https://www.seven97.top
公众号:seven97,欢迎关注~

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4