[SpringBoot Application] SpringBoot startup extension point/common interface

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

img

ApplicationContextInitializer

org.springframework.context.ApplicationContextInitializer

ConfigurableApplicationContextThis is the callback interface that the entire spring container initializes before refreshing . Simply put, it is initializethe 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 beanFactoryan extended interface, and the calling time is after spring reads beanDefinitionthe 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 beanDefinitionmeta 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 BeanPostProcessthe interface, the difference is as follows:

BeanPostProcessThe interface is only extended in the initialization phase of the bean (before and after injecting the spring context), and InstantiationAwareBeanPostProcessorthe 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 bean
  • postProcessAfterInstantiation: After the bean is instantiated, it is equivalent to the new bean
  • postProcessPropertyValues: The bean has been instantiated and is triggered when the property is injected. @Autowired, @Resourceand 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.

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 before postProcessBeforeInstantiation(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 occurs postProcessBeforeInstantiationlater, 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 later postProcessAfterInstantiation. 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 setBeanFactoryis to get BeanFactorythis property.

The usage scenario is that you can get it after the bean is instantiated but before it is initialized. BeanFactoryAt this time, you can make special customizations for each bean. Or you can take BeanFactoryit 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

insert image description here

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: EnviromentAwareAn 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: StringValueResolverAn extension class for obtaining, StringValueResolverused to obtain Stringvariables of type-based properties. Generally, we use @Valuethe same way to obtain them. If this Aware interface is implemented, cache it StringValueResolverand use this class to obtain Stringtype variables. The effect is the same.
  • ResourceLoaderAwareResourceLoader: An extension class for obtaining , ResourceLoaderwhich can be used to obtain all resource objects in the classpath, and can be extended to obtain ResourceLoaderobjects.
  • ApplicationEventPublisherAware: ApplicationEventPublisherAn extension class used for acquisition, ApplicationEventPublisherwhich can be used to publish events and ApplicationListenerbe used together in combination, which ApplicationListenerwill be mentioned in detail in the introduction below. This object can also be obtained through spring injection.
  • MessageSourceAware: MessageSourceAn extension class for acquisition, MessageSourcemainly used for internationalization.
  • ApplicationContextAwareApplicationContext: An extension class used to obtain ApplicationContext, 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, ApplicationContextit also implements BeanFactory, MessageSource, ApplicationEventPublisherand 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, postProcessBeforeInitializationbefore 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 postProcessBeforeInitializationafter and InitializingBean.afterPropertiesSetbefore.

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. InitializingBeanThe interface provides a way for the bean to initialize the method. It only includes afterPropertiesSetthe method. All classes that inherit the interface will execute the method when the bean is initialized. The trigger timing of this extension point is postProcessAfterInitializationbefore.

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.FactoryBeanfactory class interface for this purpose, and users can customize the logic of instantiating beans by implementing this interface. FactoryBeanThe interface occupies an important position for the Spring framework, and Spring itself provides more than 70 FactoryBeanimplementations. They hide the details of instantiating some complex beans, which brings convenience to upper-level applications. Starting from Spring 3.0, FactoryBeangenerics 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 postProcessAfterInitializationlater.

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 @Orderto 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 ApplicationListenercan 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 in ConfigurableApplicationContextinterfaces using refresh()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 the ApplicationContextcontainer is ready for use.
  • ContextStartedEvent This event is published
    when started using theConfigurableApplicationContext start() method in the (ApplicationContext subinterface) interface . ApplicationContextYou can poll your database, or you can restart any stopped applications after receiving this event.
  • ContextStoppedEvent This event is published when stopped
    using ConfigurableApplicationContextthe interface . You can do the necessary cleanup after receiving this eventstop()ApplicationContext
  • ContextClosedEvent is published when a Context is closed
    using the method in ConfigurableApplicationContextthe 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

Guess you like

Origin blog.csdn.net/qq_45297578/article/details/128547865