1. The execution order of Spring extension points
1.1. Spring extension points
1.1.1, spring BeanFactoryPostProcessor
Bean factory post-processor, used primarily to load BeanDefinition in Spring.
methods
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
You can use the beanFactory to define and modify beandefinitions of beans.
Element loading in Spring: All BeanDefinitions in the project have been loaded, but the normal Bean has not been instantiated and initialized.
Prohibited items
1. Forbid premature initialization of beans, after which BeanPostProcessor’s implementation class will not be able to handle the current Bean, such as the most common dynamic proxy post-processor, which means that the current Bean will fail to be proxy invalidated. Give me a baby corn. You can’t do that. ->
public class TestBean {
}
@Component
public class TestPostProcess implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
beanFactory.registerSingleton("testBean",new TestBean());
}
}
Copy the code
Of course, if you just don’t need to be processed by the BeanPostProcessor, this can be ignored.
Disallow dependency injection, because the normal Bean has not been created yet, the object will not be injected, and the value of the call will be null.
@Component public class TestBean { } @Component public class TestPostProcess implements BeanFactoryPostProcessor { @Autowired private TestBean testBean; @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { // Null system.out.println (testBean) will be printed; }}Copy the code
To implement the class call: org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(org.springframewo rk.beans.factory.config.ConfigurableListableBeanFactory, java.util.List
)
1.1.2, BeanDefinitionRegistryPostProcessor
Inheritance in spring BeanFactoryPostProcessor class, new postProcessBeanDefinitionRegistry method.
The new method
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
Scan for BeanDefinitions in the add project.
Element loading in Spring: All BeanDefinitions in the project have been loaded, but the normal Bean has not been instantiated and initialized.
Prohibited items
1, to ban the use of BeanDefinitionRegistryPostProcessor implementation class registered BeanDefinitionRegistryPostProcessor implementation class, This is registered BeanDefinitionRegistryPostProcessor postProcessBeanDefinitionRegistry 】 【 method will not be executed. Like can’t do this ->
@Component public class TestBean1DefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor , PriorityOrdered { @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { beanFactory.registerSingleton("testBeanDefinitionRegistryPostProcessor",new TestBeanDefinitionRegistryPostProcessor()); } @Override public int getOrder() { return 1; } } public class TestBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor { @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { System.out.println(" I can't execute "); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { } }Copy the code
To implement the class call: org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(org.springframewo rk.beans.factory.config.ConfigurableListableBeanFactory, java.util.List
)
Use skills
@Component public class TestBean1DefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor , PriorityOrdered { @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { registry.registerBeanDefinition("testBean",new RootBeanDefinition(TestBean.class)); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { beanFactory.registerSingleton("testBeanDefinitionRegistryPostProcessor",new TestBeanDefinitionRegistryPostProcessor()); } @Override public int getOrder() { return 1; }}Copy the code
1.1.3, BeanPostProcessor
Bean post-processor, often with some Bean processing, such as the most common dynamic proxy.
methods
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException
You can do things to the Bean, such as replace.
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException
You can do things to the Bean, such as replace.
Element loading in Spring: All beans in the project have been created and their properties have been automatically assembled. The initialization method has not been called yet.
Prohibited items
Note that the Bean is registered with registerBeanDefinition. After the Bean is registered with registerBeanDefinition, the Bean’s initialization method will be executed when the Bean is actually called. For example, dependency injection, where doGetBean is used for instance creation and initialization.
@Component public class TestBean { @Autowired private TestBean1 testBean1; @PostConstruct public void init(){ System.out.println(666); System.out.println(testBean1); } } public class TestBean1 { @PostConstruct public void init(){ System.out.println(333); } } @Component public class TestPostProcessor implements BeanPostProcessor { @Autowired private BeanFactory beanFactory; @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { BeanDefinitionRegistry beanDefinitionRegistry = (BeanDefinitionRegistry) this.beanFactory; String registerBeanName = "testBean1"; if (! beanDefinitionRegistry.containsBeanDefinition(registerBeanName)) { beanDefinitionRegistry.registerBeanDefinition(registerBeanName, new RootBeanDefinition(TestBean1.class)); } return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; }}Copy the code
2. Do not use registerSingleton to register the Bean, otherwise the Bean’s initialization method will not be executed and the post-processor will not process the current Bean. I’ll look at the reasons for this in dependency injection. Here’s the result: since the Bean instance registered with the current method already exists, there is no instance creation and dependency injection, so there is no initialization method.
@Component
public class TestPostProcessor implements BeanPostProcessor {
@Autowired
private BeanFactory beanFactory;
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
ConfigurableListableBeanFactory beanDefinitionRegistry = (ConfigurableListableBeanFactory) this.beanFactory;
String registerBeanName = "testBean1";
if (!beanDefinitionRegistry.containsBean(registerBeanName)) {
beanDefinitionRegistry.registerSingleton(registerBeanName, new TestBean1());
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
Copy the code
3. Disallow the use of dependency injection plain beans, which will cause the Bean to be initialized too early to be processed by the post-processor.
@Component public class TestPostProcessor implements BeanPostProcessor { @Autowired private TestBean1 testBean1; @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; }}Copy the code
or
@Configuration public class TestConfig { @Bean public TestPostProcessor testPostProcessor(TestBean1 testBean1){ return new TestPostProcessor(); }}Copy the code
The classic counterexample is this configuration in Shiro’s framework:
@Bean
public DefaultWebSecurityManager securityManager(ShiroRealm shiroRealm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(shiroRealm);
DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
securityManager.setSubjectDAO(subjectDAO);
return securityManager;
}
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
\
Map<String, Filter> filters = shiroFilterFactoryBean.getFilters();
shiroFilterFactoryBean.setFilters(filters);
shiroFilterFactoryBean.setFilterChainDefinitionMap(new HashMap<>());
return shiroFilterFactoryBean;
}
Copy the code
If an object is dependency injected into a ShiroRealm, then all proxies are invalided, i.e. transaction rollback is invalided.
Register beans in BeanFactoryPostProcessor. If the implementation wants to use it, it can consider annotating @lazy on beans that need to be injected. Of course, if you don’t mind the above disadvantages, please ignore these prohibitions.
To implement the class call: org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitializatio N and org. Springframework. Beans. Factory. Support. AbstractAutowireCapableBeanFactory# applyBeanPostProcessorsAfterInitializatio n
1.1.4. Custom init method
Bean initialization method. You can specify the initialization method @bean (initMethod = “initMethod”) in the Bean definition.
Org. Springframework. Beans. Factory. The annotation. InitDestroyAnnotationBeanPostProcessor. LifecycleMetadata# invokeInitMethods.
Spring element loading: Has been instantiated and dependency injection, in InitDestroyAnnotationBeanPostProcessor postProcessBeforeInitialization calls, its implementation PriorityOrdered, order = 2147483647
1.1.5. Annotation method of @postconstruct annotation
Bean initialization method.
Call: org. Springframework. Beans. Factory. The annotation. InitDestroyAnnotationBeanPostProcessor# postProcessBeforeInitialization
1.1.6, Aware
Some of Spring’s internal resources are available through the various implementation classes that implement Aware, such as BeanFactoryAware and EnvironmentAware. Spring will inject various resources as callbacks.
@Component public class TestBeanFactoryAware implements BeanFactoryAware { @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { beanFactory.getBean("testBean"); }}Copy the code
1.1.7, SmartInitializingSingleton
An extension point after all beans are instantiated, initialized, and processed by all backend processors
methods
void afterSingletonsInstantiated();
Implementation class call: org. Springframework. Beans. Factory. Support. DefaultListableBeanFactory# preInstantiateSingletons
1.2. Execution sequence of extension points
Spring BeanFactoryPostProcessor (internal execution order please refer to www.nblogs.cn/doc/spring/.)
= = = = >
BeanPostProcessor postProcessBeforeInitialization, BeanPostProcessor postProcessAfterInitialization (including initialization method in them)
= = = = >
The SmartInitializingSingleton afterSingletonsInstantiated