Foreword
Clarify Bean Spring container management process will help us to better develop a more rational design based on needs, improve system scalability and efficiency.
Bean Lifecycle
Below to sort Bean Spring container life cycle by a simple example.
We from the whole to the details, first of all is to start a container loaded Bean, it's a whole process.
/**
* 测试 Spring Bean 生命周期
* @author zyj
*/
public class LifeCycleTest {
@Test
public void testLifeCycle() {
// 通过注解开启容器,并加载Bean
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(GlobalConfig.class);
// 关闭容器
context.close();
}
}
@Configuration
public class GlobalConfig {
@Bean
public Calculator calculator() {
return new Calculator();
}
/**
* @Order:加载到容器的优先级,越小代表优先级越高
* @return
*/
@Order(0)
@Bean
public FullyBeanPostProcessor fullyBeanPostProcessor() {
return new FullyBeanPostProcessor();
}
}
Then take a look at when the container is loaded Bean have done what treatment.
We need to join Bean Spring-specific interface, these interfaces can be seen as intervention in the process of loading to the developers Bean's entrance.
public class Calculator implements BeanNameAware, ApplicationContextAware {
public Calculator() {
System.out.println("<<<构造器执行>>>");
}
@Override
public void setBeanName(String name) {
System.out.println("<<<BeanNameAware.setBeanName执行>>>");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("<<<ApplicationContextAware.setApplicationContext执行>>>");
}
@PostConstruct
public void init() {
System.out.println("<<<@PostConstruct执行>>>");
}
@PreDestroy
public void destroy() {
System.out.println("<<<@PreDestroy执行>>>");
}
}
From here you can see the code has the following interfaces and notes:
BeanNameAware
: Get the current name in the container BeanApplicationContextAware
: The current injected into the container Bean@PostConstruct
: Initialization method (corresponding to the init-method Spring configuration file, the interfaceInitializingBean
)@PreDestroy
: Destruction method (corresponding to destroy-method Spring configuration file, the interfaceDisposableBean
)
Execution order
三月 06, 2020 3:09:52 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@4f47d241: startup date [Fri Mar 06 15:09:52 CST 2020]; root of context hierarchy
三月 06, 2020 3:09:52 下午 org.springframework.context.support.PostProcessorRegistrationDelegate$BeanPostProcessorChecker postProcessAfterInitialization
信息: Bean 'globalConfig' of type [class com.zyj.spring.config.GlobalConfig$$EnhancerBySpringCGLIB$$5aa1013d] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
<<<构造器执行>>>
<<<BeanNameAware.setBeanName执行>>>
<<<ApplicationContextAware.setApplicationContext执行>>>
<<<BeanPostProcessor.postProcessBeforeInitialization执行>>>
<<<@PostConstruct执行>>>
<<<BeanPostProcessor.postProcessAfterInitialization执行>>>
三月 06, 2020 3:09:52 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
信息: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@4f47d241: startup date [Fri Mar 06 15:09:52 CST 2020]; root of context hierarchy
<<<@PreDestroy执行>>>
Process finished with exit code 0
Careful small partner must have noticed BeanPostProcessor
the execution, I Calculator
did not realize this interface, why when loaded will print it?
At first I thought deserved to be implemented by each Bean BeanPostProcessor
, so that you can @PostConstruct
be treated before and after execution.
But I was wrong, the result is validated when loading the current Bean did not do what it achieved BeanPostProcessor
.
After looking for some information, did not know BeanPostProcessor
the usage.
Look at the above configuration class, you may not have been GlobalConfig
in FullyBeanPostProcessor
.
public class FullyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof Calculator) {
System.out.println("<<<BeanPostProcessor.postProcessBeforeInitialization执行>>>");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof Calculator) {
System.out.println("<<<BeanPostProcessor.postProcessAfterInitialization执行>>>");
}
return bean;
}
}
BeanPostProcessor
Be performed by a separate class, class unified by the process performed to determine which of which Bean.
Scenarios
ApplicationContextAware
Action: by which the container can be obtained Spring
Scenario: When the instance and not to Spring management, we can not use automatic injected. For example Utils use Dao, this time can be obtained by Dao assembly held a Spring container.
@Component
public class SpringJobBeanFactory implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringJobBeanFactory.applicationContext=applicationContext;
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) throws BeansException {
if (applicationContext == null){
return null;
}
return (T)applicationContext.getBean(name);
}
}
使用:
TypeDao typeDao = SpringJobBeanFactory.getBean("typeDao");