[SpringBoot Application] SpringBoot startup extension point/common interface
- Interfaces commonly used by SpringBoot
- ApplicationContextInitializer
- BeanDefinitionRegistryPostProcessor
- BeanFactoryPostProcessor
- InstantiationAwareBeanPostProcessor
- SmartInstantiationAwareBeanPostProcessor
- BeanFactoryAware
- ApplicationContextAwareProcessor
- BeanNameAware
- @PostConstruct
- InitializingBean
- FactoryBean
- SmartInitializingSingleton
- CommandLineRunner
- DisposableBean
- ApplicationListener
Interfaces commonly used by SpringBoot
1. The BeanFactoryAware interface exposes the BeanFactory: implement the interface method to get the exposed BeanFactory
2. The ResourceLoaderAware interface exposes ResourceLoader: implement this interface to obtain the resource loader and obtain external resource files
3. The BeanNameAware interface exposes the beanName: implement this interface to obtain the bean name
4. The MessageSourceAware interface exposes MessageSource: the implementation of this interface can set international information replacement
5. The EnvironmentAware interface exposes Environment: Get all configuration information and inherit PropertyResolver to get key-value
6. ApplicationContextAware interface exposes ApplicationContext: implementing this interface can obtain container context (ApplicationContext interface inherits BeanFactory, including Environment, MessageSource, ApplicationEventPublisher, ResourceLoader basically covers all the above functions)
7. ServletContextAware interface exposes ServletContext: get Servlet context information
8. The ServletConfigAware interface exposes ServletConfig: including the ability to obtain ServletContext
9. The InstantiationAwareBeanPostProcessor interface performs some operations before and after Bean instantiation. We are actually very familiar with this interface. This interface is our old friend when we analyze the annotation configuration AOP. In fact, the annotation configuration AOP indirectly implements the BeanPostProcess interface, and InstantiationAwareBeanPostProcessor inherits this interface.
10. After the CommandLineRunner interface container is initialized and executed, the set environment variable parameters can be obtained
11. Execute the code after the ApplicationRunner interface container is initialized
12. BeanPostProcessor interface: processing before and after bean instantiation, the implementation of this interface can be operated before and after bean instantiation, similar to the operation of the interface BeanFactoryPostProcessor after the bean (BeanDefinitionsMap) is registered
13. InitializingBean interface: execute when initializeBean, that is, execute the interface method afterPropertiesSet after BeanPostProcessor executes before
14. ImportBeanDefinitionRegistrar interface: registerBeanDefinitions bean is registered to BeanDefinitionsMap
15. ImportSelector interface, return all classname arrays, call to get when registering beans, and then put in BeanDefinitionsMap and ImportBeanDefinitionRegistrar are somewhat similar
16. DeferredImportSelector interface: inherits the ImportSelector interface, which has similar functions, except that the interface is delayed to be registered. After the ImportSelector interface registers the bean, it will then register the DeferredImportSelector bean
17. ApplicationListener interface: monitoring interface. When the bean is initialized and loaded successfully, the event will be triggered. It will be called when the last step is finishRefresh. Implementing the ApplicationListener interface can receive monitoring actions
18. ApplicationContextInitializer interface: Before refreshing the container, that is, when prepareContext is traversed and called, that is, called before bean registration
19. FactoryBean interface: customize the creation process of Bean, put the object into beanFactory
ApplicationContextInitializer
org.springframework.context.ApplicationContextInitializer
ConfigurableApplicationContext
This is the callback interface that the entire spring container initializes before refreshing . Simply put, it is initialize
the method of this class that is called 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.
ApplicationContextInitializer is the original concept of the Spring framework. The main purpose of this class is to allow us to further set or process the instance of ConfigurableApplicationContext before refreshing the ApplicationContext of the ConfigurableApplicationContext type (or subtype).
The conceivable scenario 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.
public class MyApplicationContextInitializer implements ApplicationContextInitializer {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
System.out.println("-----MyApplicationContextInitializer initialize-----");
}
}
Because the spring container has not been initialized at this time, there are three ways to make your own extension take effect:
Method 1. The startup class is added using the SpringApplication object
@SpringBootApplication
public class SpringExtApplication {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(SpringExtApplication.class);
application.addInitializers(new MyApplicationContextInitializer());
application.run(args);
}
}
Method 2, application.yml/application.properties configuration file configuration
# yml
context:
initializer:
classes: cn.zysheep.ext.MyApplicationContextInitializer
# properties
context.initializer.classes=cn.zysheep.ext.MyApplicationContextInitializer
Method 3, Spring SPI extension, add in resources/META-INF/spring.factories
# Initializers
org.springframework.context.ApplicationContextInitializer=\
cn.zysheep.ext.MyApplicationContextInitializer
The three methods are configured at the same time, and they will take effect at the same time
BeanDefinitionRegistryPostProcessor
org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor
This interface is executed after reading the project beanDefinition
, providing a supplementary extension point
Usage scenario: You can dynamically register your own here beanDefinition
, and you can load beans outside the classpath
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");
}
}
BeanFactoryPostProcessor
org.springframework.beans.factory.config.BeanFactoryPostProcessor
This interface is beanFactory
an extended interface, and the calling time is after spring reads beanDefinition
the information and before instantiating the bean.
At this time, users can implement this extension interface to handle some things by themselves, such as modifying the registered beanDefinition
meta information.
public class TestBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("[BeanFactoryPostProcessor]");
}
}
InstantiationAwareBeanPostProcessor
org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor
The interface inherits BeanPostProcess
the interface, the difference is as follows:
BeanPostProcess
The interface is only extended in the initialization phase of the bean (before and after injecting the spring context), and InstantiationAwareBeanPostProcessor
the interface adds 3 methods on this basis, increasing the extensible scope to the instantiation phase and the attribute 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 beanpostProcessAfterInstantiation
: After the bean is instantiated, it is equivalent to the new beanpostProcessPropertyValues
: The bean has been instantiated and is triggered when the property is injected.@Autowired
,@Resource
and other annotation principles are implemented based on this methodpostProcessBeforeInitialization
: Before the bean is initialized, it is equivalent to injecting the bean into the spring contextpostProcessAfterInitialization
: 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.
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;
}
SmartInstantiationAwareBeanPostProcessor
org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor
The extension interface has 3 trigger point methods:
predictBeanType
: The trigger point happened beforepostProcessBeforeInstantiation
(it is not marked in the figure, because it is generally not necessary to expand this point), this method is used to predict the type of Bean, return the first Class type that is predicted successfully, and return null if it cannot be predicted; When you call,BeanFactory.getType(name)
when the bean type information cannot be obtained through the bean name, the callback method is called to determine the type information.determineCandidateConstructors
: This trigger point occurspostProcessBeforeInstantiation
later, and is used to determine the constructor of the bean, and returns a list of all constructors of the bean. Users can extend this point to customize the selection of the corresponding constructor to instantiate the bean.getEarlyBeanReference
: This trigger point occurs laterpostProcessAfterInstantiation
. When there is a circular dependency scenario, when the bean is instantiated, in order to prevent circular dependency, the callback method will be exposed in advance for post-processing of bean instantiation. This method is triggered in the callback method exposed in advance.
The extension method is:
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;
}
}
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 setBeanFactory
is to get BeanFactory
this property.
The usage scenario is that you can get it after the bean is instantiated but before it is initialized. BeanFactory
At this time, you can make special customizations for each bean. Or you can take BeanFactory
it and cache it for future use.
The extension method is:
public class TestBeanFactoryAware implements BeanFactoryAware {
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("[TestBeanFactoryAware] " + beanFactory.getBean(TestBeanFactoryAware.class).getClass().getSimpleName());
}
}
ApplicationContextAwareProcessor
org.springframework.context.support.ApplicationContextAwareProcessor
The class itself has no extension points, but there are 6 extension points inside the class that can be implemented. These classes are triggered after the bean is instantiated and before initialization
It can be seen that this class is used to implement various driver interfaces. After the bean is instantiated and the attributes are filled, the variables of the corresponding container are obtained by executing the extended interface marked in the red box above. So here it should be said that there are 6 extension points , let’s put them together here
EnvironmentAware
:EnviromentAware
An extension class used to obtain, this variable is very useful, and can obtain all parameters in the system. Of course, I personally think that there is no need to expand this Aware, because the inside of spring can be directly obtained by injection.EmbeddedValueResolverAware
:StringValueResolver
An extension class for obtaining,StringValueResolver
used to obtainString
variables of type-based properties. Generally, we use@Value
the same way to obtain them. If this Aware interface is implemented, cache itStringValueResolver
and use this class to obtainString
type variables. The effect is the same.ResourceLoaderAware
ResourceLoader
: An extension class for obtaining ,ResourceLoader
which can be used to obtain all resource objects in the classpath, and can be extended to obtainResourceLoader
objects.ApplicationEventPublisherAware
:ApplicationEventPublisher
An extension class used for acquisition,ApplicationEventPublisher
which can be used to publish events andApplicationListener
be used together in combination, whichApplicationListener
will be mentioned in detail in the introduction below. This object can also be obtained through spring injection.MessageSourceAware
:MessageSource
An extension class for acquisition,MessageSource
mainly used for internationalization.ApplicationContextAware
ApplicationContext
: An extension class used to obtainApplicationContext
, which should be a class that many people are very familiar with, is the spring context manager, which can manually obtain any bean registered in the spring context. We often extend this interface to cache the spring context and package it into static method. At the same time,ApplicationContext
it also implementsBeanFactory
,MessageSource
,ApplicationEventPublisher
and other interfaces, which can also be used to do related interface things.
BeanNameAware
org.springframework.beans.factory.BeanNameAware
It can be seen that this class is also a kind of Aware extension. The trigger point is before the initialization of the bean, that is, postProcessBeforeInitialization
before the trigger point method of this class is only one:setBeanName
The usage scenario is: users can expand this point, get the beanName registered in the spring container before initializing the bean, and modify the value of the beanName by themselves.
The extension method is:
public class NormalBeanA implements BeanNameAware{
public NormalBeanA() {
System.out.println("NormalBean constructor");
}
@Override
public void setBeanName(String name) {
System.out.println("[BeanNameAware] " + name);
}
}
@PostConstruct
javax.annotation.PostConstruct
This is not an extension point, but an annotation. Its role is in the initialization phase of the bean. If a method is marked @PostConstruct
, it will be called first. The point here is to pay attention to the trigger point of this standard, which is postProcessBeforeInitialization
after and InitializingBean.afterPropertiesSet
before.
Usage scenario: users can mark a certain method to initialize a certain property
The extension method is:
public class NormalBeanA {
public NormalBeanA() {
System.out.println("NormalBean constructor");
}
@PostConstruct
public void init(){
System.out.println("[PostConstruct] NormalBeanA");
}
}
InitializingBean
org.springframework.beans.factory.InitializingBean
This class, as the name suggests, is also used to initialize beans. InitializingBean
The interface provides a way for the bean to initialize the method. It only includes afterPropertiesSet
the method. All classes that inherit the interface will execute the method when the bean is initialized. The trigger timing of this extension point is postProcessAfterInitialization
before.
Usage scenario: The user implements this interface to initialize some business indicators when the system starts.
The extension method is:
public class NormalBeanA implements InitializingBean{
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("[InitializingBean] NormalBeanA");
}
}
FactoryBean
org.springframework.beans.factory.FactoryBean
In general, Spring uses the class attribute of the bean to specify the branch class to instantiate the bean through the reflection mechanism. In some cases, the process of instantiating the bean is more complicated. If you follow the traditional method, you need to provide a lot of configuration information in the bean . The flexibility of the configuration method is limited. At this time, a simple solution may be obtained by using the coding method. Spring provides a org.springframework.bean.factory.FactoryBean
factory class interface for this purpose, and users can customize the logic of instantiating beans by implementing this interface. FactoryBean
The interface occupies an important position for the Spring framework, and Spring itself provides more than 70 FactoryBean
implementations. They hide the details of instantiating some complex beans, which brings convenience to upper-level applications. Starting from Spring 3.0, FactoryBean
generics are supported, that is, the interface declaration is changed to FactoryBean<T>
the form
Usage scenario: The user can extend this class to act as a proxy for the bean to be instantiated, such as intercepting all the methods of the object, outputting a line of log before and after the call, and imitating the function ProxyFactoryBean
.
The extension method is:
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{
}
}
SmartInitializingSingleton
org.springframework.beans.factory.SmartInitializingSingleton
There is only one method in this interface afterSingletonsInstantiated
, and its function is to call the callback interface after all singleton objects (non-lazy loaded objects) managed by the spring container are initialized. Its trigger time is postProcessAfterInitialization
later.
Usage scenario: Users can extend this interface to do some post-processing business after all singleton objects are initialized.
The extension method is:
public class TestSmartInitializingSingleton implements SmartInitializingSingleton {
@Override
public void afterSingletonsInstantiated() {
System.out.println("[TestSmartInitializingSingleton]");
}
}
CommandLineRunner
org.springframework.boot.CommandLineRunner
This interface also has only one method: run(String... args)
, which is triggered automatically after the entire project is started. If there are more than one CommandLineRunner
, you can use them @Order
to sort them.
Usage scenario: The user extends this interface to pre-process some services after starting the project.
The extension method is:
public class TestCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("[TestCommandLineRunner]");
}
}
DisposableBean
org.springframework.beans.factory.DisposableBean
This extension point also has only one method: destroy()
, which is triggered when the object is destroyed, and this method will be executed automatically. For example, at runtime applicationContext.registerShutdownHook
, this method will be triggered.
The extension method is:
public class NormalBeanA implements DisposableBean {
@Override
public void destroy() throws Exception {
System.out.println("[DisposableBean] NormalBeanA");
}
}
ApplicationListener
org.springframework.context.ApplicationListener
To be precise, this should not be regarded as an extension point in spring&springboot, which ApplicationListener
can monitor a certain event event
, and the trigger timing can be interspersed in the execution process of the business method, and the user can customize a certain business event. But there are also some built-in events in spring, which can be interspersed in the startup call. We can also use this feature to do some built-in event listeners to achieve roughly the same thing as the previous trigger points.
Next, list the main built-in events of spring:
- ContextRefreshedEvent
This event is published when the ApplicationContext is initialized or refreshed. This can also happen inConfigurableApplicationContext
interfaces usingrefresh()
the method . The initialization here means: all Beans are successfully loaded, post-processing Beans are detected and activated, all Singleton Beans are pre-instantiated, and theApplicationContext
container is ready for use. - ContextStartedEvent This event is published
when started using theConfigurableApplicationContext
start() method in the (ApplicationContext subinterface) interface .ApplicationContext
You can poll your database, or you can restart any stopped applications after receiving this event. - ContextStoppedEvent This event is published when stopped
usingConfigurableApplicationContext
the interface . You can do the necessary cleanup after receiving this eventstop()
ApplicationContext
- ContextClosedEvent is published when a Context is closed
using the method inConfigurableApplicationContext
the interface . A closed context has reached the end of its lifetime; it cannot be refreshed or restartedclose()
ApplicationContext
- 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