【生命周期】对Spring容器中Bean的生命周期解析

本文详细解析了Spring容器中Bean的生命周期,包括初始化和销毁方法的指定、InitializingBean和DisposableBean接口、@PostConstruct和@PreDestroy注解的使用,以及BeanPostProcessor后置处理器的工作原理和应用。

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

对Spring容器中Bean的生命周期解析

1. 生命周期简介

Bean 的生命周期:
Bean创建 —》初始化 —》销毁的过程

Spring 容器管理 bean 的生命周期:
我们可以自定义初始化和销毁的方法,容器在 bean 进行到对应生命周期的的时候调用我们自定义的初始化和销毁方法

1、Bean 的构造(对象创建):
单实例时,在容器启动时创建对象
多实例时,在每次获取 bean 的时候创建对象

2、Bean 的初始化:
对象创建好时,且属性已赋值完成后,调用初始化方法

3、Bean 的销毁
Spring 容器关闭时进行 bean 的销毁

2. @Bean指定初始化和销毁方法

在 @Bean 注解的源码中,存在两个属性:initMethoddestroyMethod
即可以通过该属性指定被 @Bean 注解标注的组件的初始化方法和销毁方法

源码如下:

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Bean {
	... ...

	/**
	 * The optional name of a method to call on the bean instance during initialization.
	 * Not commonly used, given that the method may be called programmatically directly
	 * within the body of a Bean-annotated method.
	 * <p>The default value is {@code ""}, indicating no init method to be called.
	 */
	String initMethod() default "";

	String destroyMethod() default AbstractBeanDefinition.INFER_METHOD;
}

创建 Bean 实体类:

package com.jiker.bean;

public class BeanDemo1 {
	
	public BeanDemo1() {
		// TODO Auto-generated constructor stub
		System.out.println("BeanDemo1 constructor...");
	}
	
	public void init() {
		System.out.println("BeanDemo1 init...");
	}
	
	public void destroy() {
		System.out.println("BeanDemo1 destroy...");
	}
	
}

创建配置类,并注入 bean(默认为单实例对象)
使用 @Bean 注解中的两个属性指定初始化和销毁方法

package com.jiker.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.jiker.bean.BeanDemo1;

@Configuration
public class MainConfig {

	@Bean(initMethod = "init",destroyMethod = "destroy")
	public BeanDemo1 beanDemo1() {
		return new BeanDemo1();
	}
	
}

测试

package com.jiker.test;

import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.jiker.config.MainConfig;

public class TestBean {

	@Test
	public void m01() {
		
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
		System.out.println("Spring 容器创建...");
		
		//关闭容器
		applicationContext.close();
	}
}

结果:
在这里插入图片描述
多实例对象测试

	@Scope("prototype")
	@Bean(initMethod = "init",destroyMethod = "destroy")
	public BeanDemo1 beanDemo1() {

此时,运行时仅创建了 Spring 容器,并没有初始化容器中的对象
在这里插入图片描述
若获取 bean 后,容器关闭时不再销毁 bean,即:容器不管理多实例 bean 的生命周期

	AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
	System.out.println("Spring 容器创建...");
	applicationContext.getBean("beanDemo1");
		
	//关闭容器
	applicationContext.close();

在这里插入图片描述

3. InitializingBean和DisposableBean

InitializingBean:由bean实现的接口,当bean工厂设置了所有属性后,需要作出反应:例如,执行自定义初始化,或者只检查是否设置了所有强制属性。

public interface InitializingBean {

	/**
	 * Invoked by a BeanFactory after it has set all bean properties supplied
	 * (and satisfied BeanFactoryAware and ApplicationContextAware).
	 * <p>This method allows the bean instance to perform initialization only
	 * possible when all bean properties have been set and to throw an
	 * exception in the event of misconfiguration.
	 * @throws Exception in the event of misconfiguration (such
	 * as failure to set an essential property) or if initialization fails.
	 */
	void afterPropertiesSet() throws Exception;

}

DisposableBean:接口将由希望在销毁时释放资源的bean实现。如果beanfactory处理缓存的单例,那么它应该调用destroy方法。应用程序上下文应该在关闭时释放它的所有单例

public interface DisposableBean {

	/**
	 * Invoked by a BeanFactory on destruction of a singleton.
	 * @throws Exception in case of shutdown errors.
	 * Exceptions will get logged but not rethrown to allow
	 * other beans to release their resources too.
	 */
	void destroy() throws Exception;

}

即:可以创建一个实体类,分别实现 InitializingBean 和 DisposableBean 接口,这样 Spring 容器就会在对应的时期调用对应的接口方法,完成 bean 的初始化或销毁

BeanDemo2.java

package com.jiker.bean;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

//将该实例注入容器中
@Component
public class BeanDemo2 implements InitializingBean,DisposableBean {
	
	public BeanDemo2() {
		// TODO Auto-generated constructor stub
		System.out.println("BeanDemo2 constructor...");
	}

	//实现DisposableBean中的方法
	public void destroy() throws Exception {
		// TODO Auto-generated method stub
		System.out.println("BeanDemo2 DisposableBean.destroy ...");
	}

	//实现InitializingBean中的方法
	public void afterPropertiesSet() throws Exception {
		// TODO Auto-generated method stub
		System.out.println("BeanDemo2 InitializingBean.afterPropertiesSet ...");
	}

}

使用 @ComponentScan 包扫描方式将 BeanDemo2 注册入容器

@ComponentScan("com.jiker.bean")
@Configuration
public class MainConfig {

在这里插入图片描述

4. @PostConstruct&@PreDestroy

使用 JSR250 中的注解:
@PostConstruct:在 bean 创建完成并且属性赋值完成后,来执行标注该注解的方法
@PreDestroy:在容器销毁 bean 之前通知我们进行清理工作

package com.jiker.bean;

import org.springframework.stereotype.Component;

@Component
public class BeanDemo3 {
	
	public BeanDemo3() {
		// TODO Auto-generated constructor stub
		System.out.println("BeanDemo3 constructor...");
	}
	
	@PostConstruct
	public void init() {
		System.out.println("BeanDemo3 init...");
	}
	
	@PreDestroy
	public void destroy() {
		System.out.println("BeanDemo3 destroy...");
	}
	
}

5. BeanPostProcessor后置处理器

Spring 为我们提供了一种组件:BeanPostProcessor[interface];意为 bean 的后置处理器
在 bean 初始化前后进行一些处理工作;
postProcessBeforeInitialization():在已经创建好了 bean 实例之后,且在任何初始化之前工作
postProcessAfterInitialization():在初始化之后工作

5.1 后置处理器实现

源码:

public interface BeanPostProcessor {

	/**
	 * Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean
	 * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
	 * or a custom init-method). The bean will already be populated with property values.
	 * The returned bean instance may be a wrapper around the original.
	 * @param bean the new bean instance
	 * @param beanName the name of the bean
	 * @return the bean instance to use, either the original or a wrapped one;
	 * if {@code null}, no subsequent BeanPostProcessors will be invoked
	 * @throws org.springframework.beans.BeansException in case of errors
	 * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
	 */
	Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;

	/**
	 * Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean
	 * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
	 * or a custom init-method). The bean will already be populated with property values.
	 * The returned bean instance may be a wrapper around the original.
	 * <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean
	 * instance and the objects created by the FactoryBean (as of Spring 2.0). The
	 * post-processor can decide whether to apply to either the FactoryBean or created
	 * objects or both through corresponding {@code bean instanceof FactoryBean} checks.
	 * <p>This callback will also be invoked after a short-circuiting triggered by a
	 * {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method,
	 * in contrast to all other BeanPostProcessor callbacks.
	 * @param bean the new bean instance
	 * @param beanName the name of the bean
	 * @return the bean instance to use, either the original or a wrapped one;
	 * if {@code null}, no subsequent BeanPostProcessors will be invoked
	 * @throws org.springframework.beans.BeansException in case of errors
	 * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
	 * @see org.springframework.beans.factory.FactoryBean
	 */
	Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

}

实现后置处理器接口

package com.jiker.bean;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {

	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		// TODO Auto-generated method stub
		System.out.println("postProcessBeforeInitialization  " + beanName + " =>" + bean);
		return bean;
	}

	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		// TODO Auto-generated method stub
		System.out.println("postProcessAfterInitialization  " + beanName + " =>" + bean);
		return bean;
	}

}

在这里插入图片描述

5.2 BeanPostProcessor原理

使用 DEBUG 方式查看方法栈

TestBean.m01() line: 13	
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
创建 IOC 容器

AnnotationConfigApplicationContext.<init>(Class<?>...) line: 84	
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
	this();
	register(annotatedClasses);
	refresh();
}
刷新容器

AnnotationConfigApplicationContext(AbstractApplicationContext).refresh() line: 543	
public void refresh() throws BeansException, IllegalStateException {
	... ...
	// Instantiate all remaining (non-lazy-init) singletons.
	finishBeanFactoryInitialization(beanFactory);
	... ...
}
初始化所有剩下的单实例对象

... ...//试着获取 bean,若是第一次获取,则创建 bean

DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).doCreateBean(String, RootBeanDefinition, Object[]) line: 555	
Object exposedObject = bean;
try {
	populateBean(beanName, mbd, instanceWrapper);
	if (exposedObject != null) {
		exposedObject = initializeBean(beanName, exposedObject, mbd);
	}
}
populateBean(beanName, mbd, instanceWrapper) 方法既是通过各种判断为 bean 赋值
initializeBean(beanName, exposedObject, mbd) 即是后置处理器的调用,源码如下:
	... ...
	if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}
	... ...
	try {
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
	... ...
	if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}
	... ...
initializeBean方法中存在着 invokeInitMethods,即是初始化 bean,在其之前会调用 applyBeanPostProcessorsBeforeInitialization
在其后会调用 applyBeanPostProcessorsAfterInitialization

DefaultListableBeanFactory(AbstractAutowireCapableBeanFactory).applyBeanPostProcessorsBeforeInitialization(Object, String) line: 409	
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
			throws BeansException {

		Object result = existingBean;
		for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
			result = beanProcessor.postProcessBeforeInitialization(result, beanName);
			if (result == null) {
				return result;
			}
		}
		return result;
	}
后置处理器中 XXXPostProcessBeforeInitialization 方法的原理:遍历得到容器中所有的 BeanPostProcessor,
挨个执行 beforeInitialization 方法,一旦方法返回 NULL 时,跳出循环,不会再执行后面的后者处理器

5.3 BeanPostProcessor在Spring底层的使用

BeanPostProcessor 接口的所有实现类:
在这里插入图片描述

示例:ApplicationContextAwareProcessor:给 bean 中注入 IOC容器

class ApplicationContextAwareProcessor implements BeanPostProcessor {
	... ...
	@Override
	public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
		AccessControlContext acc = null;

		if (System.getSecurityManager() != null &&
				(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
						bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
						bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
			acc = this.applicationContext.getBeanFactory().getAccessControlContext();
		}
		... ...
	}

	private void invokeAwareInterfaces(Object bean) {
		if (bean instanceof Aware) {
			if (bean instanceof EnvironmentAware) {
				((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
			}
			if (bean instanceof EmbeddedValueResolverAware) {
				((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
			}
			if (bean instanceof ResourceLoaderAware) {
				((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
			}
			if (bean instanceof ApplicationEventPublisherAware) {
				((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
			}
			if (bean instanceof MessageSourceAware) {
				((MessageSourceAware) bean).setMessageSource(this.applicationContext);
			}
			if (bean instanceof ApplicationContextAware) {
				((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
			}
		}
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) {
		return bean;
	}

}

postProcessBeforeInitialization():判断传入的 bean 中是否实现了 XXXAware 接口,
如果是的话则执行 invokeAwareInterfaces()

invokeAwareInterfaces():初始化方法,给 bean 注入值,判断实现的是哪一个 Aware
若当前是 ApplicationContextAware,则调用 setApplicationContext,给 传入的 bean 注入 applicationContext 组件

时间:2019.6.24 10:11

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值