Spring生命周期中的常见接口

本文详细解析了Spring框架中的各种生命周期管理机制,包括ApplicationContextInitializer的作用、ApplicationListener接口如何监听容器事件、InitializingBean与DisposableBean接口的应用场景及BeanPostProcessor的执行流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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();
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值