Keep these 16 SpringBoot extension interfaces in mind to write more beautiful code


1. Background

The core idea of ​​Spring is the container. When the container is refreshed, the outside looks calm, but the inside is full of turbulent waves and a vast ocean. Springboot encapsulates Spring even more, following the convention is greater than the configuration, plus the mechanism of automatic assembly. In many cases, we only need to quote a dependency, and we can complete the assembly of a function with almost zero configuration.

I like this automatic assembly mechanism very much, so I will also use this feature when developing middleware and public dependency tools myself. Allow users to access with minimum cost. If you want to play with automatic assembly, you must understand spring's construction life cycle for beans and various extension interfaces. Of course, understanding the various life cycles of beans can also promote our understanding of spring. Business code can also make reasonable use of these extension points to write more beautiful code.

In this article, I summarize almost all the extension interfaces of Spring & Springboot , as well as the usage scenarios of each extension point. And sorted out a sequential call graph of a bean from being loaded to the final initialization of all extensible points within spring. So we can also spy on how beans are loaded into the spring container step by step.

2. Extensible interface startup call sequence diagram

The following is the calling sequence of all the extensible points in the life cycle of the Bean in the spring container I organized, which will be analyzed one by one below

8ba761fa25a0ebb4cc3b0c2e7a7898a0.jpeg

3、ApplicationContextInitializer

org.springframework.context.ApplicationContextInitializer

This is the callback interface for the entire spring container to initialize the ConfigurableApplicationContext before it is refreshed . In short, it is to call the initialize method of this class before the container is refreshed. This point is allowed to be extended by the user himself. Users can do some things before the entire spring container is initialized.

The conceivable scenarios may be to activate some configurations at the beginning, or to use the opportunity when the class has not been loaded by the class loader at this time to perform operations such as dynamic bytecode injection.

The extension method is:

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

Because the spring container has not been initialized at this time, there are three ways to make your own extension take effect:

  • In the startup class, use the springApplication.addInitializers(new TestApplicationContextInitializer()) statement to join

  • Configuration file configuration context.initializer.classes=com.example.demo.TestApplicationContextInitializer

  • Spring SPI extension, add org.springframework.context.ApplicationContextInitializer=com.example.demo.TestApplicationContextInitializer to spring.factories

4、BeanDefinitionRegistryPostProcessor

org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor

This interface is executed after reading the beanDefinition in the project , providing a supplementary extension point

Usage scenario: You can dynamically register your own beanDefinition here , and you can load beans outside the classpath

The extension method is:

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");      
    }      
}      


5、BeanFactoryPostProcessor

org.springframework.beans.factory.config.BeanFactoryPostProcessor

This interface is the extended interface of beanFactory , and the calling time is after spring reads beanDefinition information and before instantiating beans.

At this time, users can implement this extension interface to handle some things by themselves, such as modifying the meta information of the registered beanDefinition .

The extension method is:

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


6、InstantiationAwareBeanPostProcessor

org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor

This interface inherits the BeanPostProcess interface, the difference is as follows:

The BeanPostProcess interface is only extended during the initialization phase of the bean (before and after injecting the spring context), and the InstantiationAwareBeanPostProcessor interface adds 3 methods on this basis, increasing the scope of scalability to the instantiation phase and the property injection phase.

The main extension points of this class have the following five methods, which are mainly in the two stages of the bean life cycle: the instantiation stage and the initialization stage , which will be explained together below, and the calling order is as follows:

  • postProcessBeforeInstantiation : Before instantiating the bean, it is equivalent to before the new bean

  • postProcessAfterInstantiation : After the bean is instantiated, it is equivalent to after the new bean

  • postProcessPropertyValues ​​: The bean has been instantiated and is triggered when the property is injected. @Autowired , @Resource and other annotation principles are implemented based on this method

  • postProcessBeforeInitialization : Before the bean is initialized, it is equivalent to injecting the bean into the spring context

  • postProcessAfterInitialization : After the bean is initialized, it is equivalent to injecting the bean into the spring context

Usage scenario: This extension point is very useful, whether it is writing middleware or business, this feature can be used. For example, collect beans that implement a certain type of interface during each life cycle, or uniformly set the value of a certain type of bean, etc.

The extension method is:

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      
&nbsp;&nbsp;&nbsp;&nbsp; public&nbsp;Object&nbsp;postProcessBeforeInstantiation(Class<?>&nbsp;beanClass,&nbsp;String&nbsp;beanName)&nbsp;throws&nbsp;BeansException&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println( "[TestInstantiationAwareBeanPostProcessor]&nbsp;before&nbsp;instantiation&nbsp;"&nbsp;+&nbsp;beanName);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp; null;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; @Override&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; public&nbsp;boolean&nbsp;postProcessAfterInstantiation(Object&nbsp;bean,&nbsp;String&nbsp;beanName)&nbsp;throws&nbsp;BeansException&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println( "[TestInstantiationAwareBeanPostProcessor]&nbsp;after&nbsp;instantiation&nbsp;"&nbsp;+&nbsp;beanName);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp; true;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; @Override&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; public&nbsp;PropertyValues&nbsp;postProcessPropertyValues(PropertyValues&nbsp;pvs,&nbsp;PropertyDescriptor[]&nbsp;pds,&nbsp;Object&nbsp;bean,&nbsp;String&nbsp;beanName)&nbsp;throws&nbsp;BeansException&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println( "[TestInstantiationAwareBeanPostProcessor]&nbsp;postProcessPropertyValues&nbsp;"&nbsp;+&nbsp;beanName);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp;pvs;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;


7、SmartInstantiationAwareBeanPostProcessor

org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor

The extension interface has 3 trigger point methods:

  • predictBeanType : This trigger point occurs before postProcessBeforeInstantiation (not marked on the figure, because it is generally not necessary to expand this point), this method is used to predict the type of Bean, and returns the first Class type that is predicted successfully. If it cannot be predicted, return null; When you call BeanFactory.getType(name), when the bean type information cannot be obtained through the bean name, call the callback method to determine the type information.

  • determineCandidateConstructors:该触发点发生在postProcessBeforeInstantiation之后,用于确定该bean的构造函数之用,返回的是该bean的所有构造函数列表。用户可以扩展这个点,来自定义选择相应的构造器来实例化这个bean。

  • getEarlyBeanReference:该触发点发生在postProcessAfterInstantiation之后,当有循环依赖的场景,当bean实例化好之后,为了防止有循环依赖,会提前暴露回调方法,用于bean实例化的后置处理。这个方法就是在提前暴露的回调方法中触发。

扩展方式为:

public&nbsp; class&nbsp;TestSmartInstantiationAwareBeanPostProcessor&nbsp;implements&nbsp;SmartInstantiationAwareBeanPostProcessor&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; @Override&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; public&nbsp;Class<?>&nbsp;predictBeanType(Class<?>&nbsp;beanClass,&nbsp;String&nbsp;beanName)&nbsp; throws&nbsp;BeansException&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println( "[TestSmartInstantiationAwareBeanPostProcessor]&nbsp;predictBeanType&nbsp;"&nbsp;+&nbsp;beanName);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp;beanClass;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; @Override&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; public&nbsp;Constructor<?>[]&nbsp;determineCandidateConstructors(Class<?>&nbsp;beanClass,&nbsp;String&nbsp;beanName)&nbsp; throws&nbsp;BeansException&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println( "[TestSmartInstantiationAwareBeanPostProcessor]&nbsp;determineCandidateConstructors&nbsp;"&nbsp;+&nbsp;beanName);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp; null;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; @Override&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; public&nbsp;Object&nbsp;getEarlyBeanReference(Object&nbsp;bean,&nbsp;String&nbsp;beanName)&nbsp;throws&nbsp;BeansException&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println( "[TestSmartInstantiationAwareBeanPostProcessor]&nbsp;getEarlyBeanReference&nbsp;"&nbsp;+&nbsp;beanName);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp;bean;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;


8、BeanFactoryAware

org.springframework.beans.factory.BeanFactoryAware

This class has only one trigger point, which occurs after the bean is instantiated and before the property is injected, that is, before the Setter. The extension point method of this class is setBeanFactory , which can get the property of BeanFactory .

The usage scenario is that you can get the   BeanFactory after the bean is instantiated but before it is initialized. At this time, you can make special customizations for each bean. Or you can get the BeanFactory for caching and use it in the future.

The extension method is:

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


9、ApplicationContextAwareProcessor

org.springframework.context.support.ApplicationContextAwareProcessor

该类本身并没有扩展点,但是该类内部却有6个扩展点可供实现 ,这些类触发的时机在bean实例化之后,初始化之前

d0fc28b46e59e448ee93fbaf7832f803.jpeg

可以看到,该类用于执行各种驱动接口,在bean实例化之后,属性填充之后,通过执行以上红框标出的扩展接口,来获取对应容器的变量。所以这里应该来说是有6个扩展点,这里就放一起来说了

  • EnvironmentAware:用于获取EnviromentAware的一个扩展类,这个变量非常有用, 可以获得系统内的所有参数。当然个人认为这个Aware没必要去扩展,因为spring内部都可以通过注入的方式来直接获得。

  • EmbeddedValueResolverAware:用于获取StringValueResolver的一个扩展类,&nbsp;StringValueResolver用于获取基于String类型的properties的变量,一般我们都用@Value的方式去获取,如果实现了这个Aware接口,把StringValueResolver缓存起来,通过这个类去获取String类型的变量,效果是一样的。

  • ResourceLoaderAware:用于获取ResourceLoader的一个扩展类,ResourceLoader可以用于获取classpath内所有的资源对象,可以扩展此类来拿到ResourceLoader对象。

  • ApplicationEventPublisherAware:用于获取ApplicationEventPublisher的一个扩展类,ApplicationEventPublisher可以用来发布事件,结合ApplicationListener来共同使用,下文在介绍ApplicationListener时会详细提到。这个对象也可以通过spring注入的方式来获得。

  • MessageSourceAware:用于获取MessageSource的一个扩展类,MessageSource主要用来做国际化。

  • ApplicationContextAware:用来获取ApplicationContext的一个扩展类,ApplicationContext应该是很多人非常熟悉的一个类了,就是spring上下文管理器,可以手动的获取任何在spring上下文注册的bean,我们经常扩展这个接口来缓存spring上下文,包装成静态方法。同时ApplicationContext也实现了BeanFactoryMessageSourceApplicationEventPublisher等接口,也可以用来做相关接口的事情。


10、BeanNameAware

org.springframework.beans.factory.BeanNameAware

可以看到,这个类也是Aware扩展的一种,触发点在bean的初始化之前,也就是postProcessBeforeInitialization之前,这个类的触发点方法只有一个:setBeanName

使用场景为:用户可以扩展这个点,在初始化bean之前拿到spring容器中注册的的beanName,来自行修改这个beanName的值。

扩展方式为:

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


11、@PostConstruct

javax.annotation.PostConstruct

This is not an extension point, but an annotation. Its function is in the initialization phase of the bean. If @PostConstruct is marked on a method , this method will be called first. The point here is to pay attention to the trigger point of this standard, which is after postProcessBeforeInitialization and before InitializingBean.afterPropertiesSet .

Usage scenario: users can mark a certain method to initialize a certain property

The extension method is:

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


12、InitializingBean

org.springframework.beans.factory.InitializingBean

This class, as the name suggests, is also used to initialize beans. The InitializingBean interface provides an initialization method for the bean, which only includes the afterPropertiesSet method. All classes that inherit this interface will execute this method when initializing the bean. The trigger timing of this extension point is before postProcessAfterInitialization .

Usage scenario: The user implements this interface to initialize some business indicators when the system starts.

The extension method is:

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


13、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的细节,给上层应用带来了便利。从Spring3.0开始,FactoryBean开始支持泛型,即接口声明改为FactoryBean<T>的形式

使用场景:用户可以扩展这个类,来为要实例化的bean作一个代理,比如为该对象的所有的方法作一个拦截,在调用前后输出一行log,模仿ProxyFactoryBean的功能。

扩展方式为:

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


14、SmartInitializingSingleton

org.springframework.beans.factory.SmartInitializingSingleton

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

使用场景:用户可以扩展此接口在对所有单例对象初始化完毕后,做一些后置的业务处理。

扩展方式为:

public&nbsp; class&nbsp;TestSmartInitializingSingleton&nbsp;implements&nbsp;SmartInitializingSingleton&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; @Override&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; public&nbsp;void&nbsp;afterSingletonsInstantiated()&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println( "[TestSmartInitializingSingleton]");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;


15、CommandLineRunner

org.springframework.boot.CommandLineRunner

这个接口也只有一个方法:run(String... args),触发时机为整个项目启动完毕后,自动执行。如果有多个CommandLineRunner,可以利用@Order来进行排序。

使用场景:用户扩展此接口,进行启动项目之后一些业务的预处理。

扩展方式为:

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


16、DisposableBean

org.springframework.beans.factory.DisposableBean

这个扩展点也只有一个方法:destroy(),其触发时机为当此对象销毁时,会自动执行这个方法。比如说运行applicationContext.registerShutdownHook时,就会触发这个方法。

扩展方式为:

public&nbsp; class&nbsp;NormalBeanA&nbsp;implements&nbsp;DisposableBean&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; @Override&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; public&nbsp;void&nbsp;destroy()&nbsp;throws&nbsp;Exception&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println( "[DisposableBean]&nbsp;NormalBeanA");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;


17、ApplicationListener

org.springframework.context.ApplicationListener

准确的说,这个应该不算spring&springboot当中的一个扩展点,ApplicationListener可以监听某个事件的event,触发时机可以穿插在业务方法执行过程中,用户可以自定义某个业务事件。

但是spring内部也有一些内置事件,这种事件,可以穿插在启动调用中。我们也可以利用这个特性,来自己做一些内置事件的监听器来达到和前面一些触发点大致相同的事情。

接下来罗列下spring主要的内置事件:

  • ContextRefreshedEvent

    ApplicationContext 被初始化或刷新时,该事件被发布。这也可以在ConfigurableApplicationContext接口中使用&nbsp;refresh()方法来发生。此处的初始化是指:所有的Bean被成功装载,后处理Bean被检测并激活,所有Singleton Bean 被预实例化,ApplicationContext容器已就绪可用。

  • ContextStartedEvent

    当使用&nbsp;ConfigurableApplicationContext&nbsp;(ApplicationContext子接口)接口中的&nbsp;start()&nbsp;方法启动&nbsp;ApplicationContext时,该事件被发布。你可以调查你的数据库,或者你可以在接受到这个事件后重启任何停止的应用程序。

  • ContextStoppedEvent

    当使用&nbsp;ConfigurableApplicationContext接口中的&nbsp;stop()停止ApplicationContext&nbsp;时,发布这个事件。你可以在接受到这个事件后做必要的清理的工作

  • ContextClosedEvent

    当使用&nbsp;ConfigurableApplicationContext接口中的&nbsp;close()方法关闭&nbsp;ApplicationContext&nbsp;时,该事件被发布。一个已关闭的上下文到达生命周期末端;它不能被刷新或重启

  • RequestHandledEvent

    This is a web-specific event that tells all beans that the HTTP request has been serviced. Can only be applied to web applications using DispatcherServlet. When using Spring as the front-end MVC controller, the system will automatically trigger this event when Spring finishes processing user requests

18. Finally

From these spring&springboot extension points, we can roughly see the entire bean life cycle. When developing business or writing middleware business, we can make reasonable use of the extension points provided by spring to do some things in each stage of spring startup. In order to achieve the purpose of custom initialization.

original:

Guess you like

Origin blog.csdn.net/zhaomengsen/article/details/132124825