SPRING自身生命周期
ApplicationContextInitializer
在refresh之前被调用
比如著名的应用是在springboot启动前向容器注入配置
注意需要在spring.factories文件中进行如下配置
org.springframework.context.ApplicationContextInitializer=com.learn.springboot.initializer.FirstInitializer
此外,在springboot项目中,可以使用代码配置
SpringApplication springApplication = new SpringApplication(SpringbootApplication.class);
springApplication.addInitializers(new SecondInitializer());
springApplication.run();
其他的主要生命周期是监听事件实现的(当然也支持自定义事件)
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
/**
* Handle an application event.
* @param event the event to respond to
*/
void onApplicationEvent(E event);
}
容器自定义的事件常用的有以下四个
ContextClosedEvent(容器关闭时)
ContextRefreshedEvent(容器刷新是)
ContextStartedEvent(容器启动时候)
ContextStoppedEvent(容器停止的时候
Bean的生命周期接口
主要看一段源代码就可以了
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
//执行各种Aware。注意,context的aware不在这。
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//1.执行ApplicationContextAwareProcessor。内部执行context的aware的。
//2.指定各种自定义的postprocessor。
//3.@postconstruct定义的也再次执行,优先级最低。
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
//调用各种init。包含afterpropertiesset和用户定义的init方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
//执行各种自定义的postprocessor
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
InitializingBean.afterPropertiesSet()
这个方法将在所有的属性被初始化后调用。这个时声明的针对具体bean的。
public interface InitializingBean {
void afterPropertiesSet() throws Exception;
}
DisposableBean.destroy()
这个方法将在bean在销毁时调用,这个声明时针对具体类的。
以上这两个接口窃以为都是为不习惯在配置文件中写init-method和destroy-method的人提供。
BeanPostProcessor
BeanPostProcessor是Spring中定义的一个接口,其与之前介绍的InitializingBean和DisposableBean接口类似,也是供Spring进行回调的。里面包含postProcessBeforeInitialization和postProcessAfterInitialization。【所有bean都会经过这些方法。】
InstantiationAwareBeanPostProcessor
是上面接口的子接口。postProcessBeforeInstantiation将在具体bean进入构造函数之前执行,而postProcessPropertyValues将在bean结束构造函数执行。和他的父接口不同,这个接口的实现类不需要手工绑定。
各种Aware
- BeanClassLoaderAware
public interface BeanClassLoaderAware extends Aware {
void setBeanClassLoader(ClassLoader var1);
}
- ApplicationContextAware
public interface ApplicationContextAware extends Aware {
void setApplicationContext(ApplicationContext var1) throws BeansException;
}
总结如下:
建立时:
postProcessBeforeInitialization(所有) -> InitializingBean.afterPropertiesSet(单个) -> init-method(单个) -> postconstruct (单个) -> 单个bean set进入scopse -> postProcessAfterInitialization(所有)
销毁时
DisposableBean.destroy -> destroy-method
Spring声明周期接口
Spring的启动
context = new ClassPathXmlApplicationContext(new String[]{
"applicationContext.xml"
类似这样的代码是无法启动Spring的!!这样写的化Spring的启动发生在你第一次getbean。当然,你可以手动调用
context.start()
Spring启动的第一件事就是加载配置文件。
实例化并执行BeanDefinitionRegistryPostProcessor
如果一个bean实现了这个接口,在所有bean完成定义注册时,spring将调用这个方法一次。在这个方法里,你可以手动新增bean。这也意味着BeanDefinitionRegistryPostProcessor的实现bean将被在这个步骤之前完成了实例化。
实例化并执行BeanFactoryPostProcessor
在bean实例化之前执行的。也就是说,Spring允许BeanFactoryPostProcessor在容器创建bean之前读取bean配置元数据,并可进行修改。这也意味着BeanFactoryPostProcessor的实现bean将被在这个步骤之前完成了实例化。
实例化InstantiationAwareBeanPostProcessor。
此时,spring已经完成准备工作。将抛出ContextRefreshedEvent事件。
以上两者的总结如下图
另外一张很有用的图为
例子
SpringMVC想在容器全部初始化完成后在执行一个方法
public class InternalSpringListener implements ApplicationListener<ContextRefreshedEvent> {
public static void setIsSpringMVC(boolean isSpringMVC) {
InternalSpringListener.isSpringMVC = isSpringMVC;
}
private static volatile boolean isSpringMVC = false;
private static Logger logger = LoggerFactory.getLogger(InternalSpringListener.class);
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
logger.info("trolley InternalSpringListener initial");
ApplicationContext context = event.getApplicationContext();
if(isSpringMVC){
if(context.getParent() == null){//这个是为了区分是否为TT
return;
}
}
AbstractMessageListener listener = (AbstractMessageListener)context.getBean("trollyConsumeListener");
ConsumerClient cc = new ConsumerClient(listener);
cc.beginReceive();
}
}