Bean创建-初始化-销毁 的过程

给容器中注入组件的方式
  • 包扫描+组件标注注解(@Controller/@Service/@Repository/@Component)
  • @Bean[导入的第三方包里面的组件]
  • @Import【快速的给容器中导入一个组件】
    • @Import(要导入容器中的组件);容器就会注入这个类,id是class的全限类名
    • 实现ImportSelector接口:返回需要导入的组名的全限类名
    • 实现ImportBeanDefinitionRegistrar接口:手动注册Bean到容器中
  • 使用Spring提供的FactoryBean(工厂Bean)
    • 默认获取到的是工厂Bean调用getObject创建的对象
    • 想要获取工厂Bean本身,需要在getBean的时候,id最前面加&标志符
Bean的生命周期

Bean的生命周期: bean创建—初始化—销毁 的过程
容器管理Bean的生命周期
我们可以自定义初始化和销毁方法,容器在Bean进行到当前生命周期的时候来调用我们自定义的初始化和销毁方法
Bean经历的基本过程:

  1. 构造(对象创建):

​ 单实例:在容器启动的时候创建对象

​ 多实例:在每次获取的时候创建对象

BeanPostProcessor.postProcessBeforeInitialization

  1. 初始化:

​ 对象创建完成,并赋值后,调用初始化方法

BeanPostProcessor.postProcessAfterInitialization

  1. 销毁:

​ 单实例:在容器关闭的时候调用销毁方法

​ 多实例:容器不会管理这个Bean,容器不会调用销毁方法
自定义Bean初始化销毁方法

  • 指定Bean 的初始化和销毁方法==>指定init-method和destroy-method@Bean(initMethod = "init",destroyMethod = "destroy")
  • 通过让Bean实现InitializingBean接口的afterPropertiesSet方法定义初始化逻辑;实现DisposableBean接口的destroy方法定义销毁逻辑
  • 可以使用JSR250:
    • @PostConstruct:在Bean创建完成并且属性赋值完成后,执行初始化方法
    • @PreDestroy:在容器销毁之前调用
  • BeanPostProcessor:Bean的后置处理器;在Bean的初始化前后进行一些处理工作
    • postProcessBeforeInitialization在初始化之前调用
    • postProcessAfterInitialization在初始化之后调用
demo测试
  1. 创建一个MyBeanPostProcessor类实现BeanPostProcessor接口
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		System.out.println(beanName+"初始化之前=>"+bean.getClass());
		return bean;
	}
	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		System.out.println(beanName+"初始化之后=>"+bean.getClass());
		return bean;
	}
}
  1. 创建一个类Cat,注入到Spring中
@Component
public class Cat implements InitializingBean, DisposableBean {
	public Cat() {
		System.out.println("cat...constructor");
	}
	@Override
	public void destroy() throws Exception {
		System.out.println("cat...destroy...");
	}
	@Override
	public void afterPropertiesSet() throws Exception {
		System.out.println("cat...init...");
	}
}
  1. 创建一个配置类MyConfig
@Configuration
@ComponentScan("com.yang.lifecycle")
public class MyConfig {

}
  1. 最后是测试类Test
public class MyTest {
	@Test
	public void yangTest(){
		AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(MyConfig.class);
		ac.close();
	}
}
  1. 运行结果
myConfig初始化之前=>class com.yang.lifecycle.config.MyConfig$$EnhancerBySpringCGLIB$$51ed062e
myConfig初始化之后=>class com.yang.lifecycle.config.MyConfig$$EnhancerBySpringCGLIB$$51ed062e
cat...constructor
cat初始化之前=>class com.yang.lifecycle.bean.Cat
cat...init...
cat初始化之后=>class com.yang.lifecycle.bean.Cat
cat...destroy...
Spring源码探究

老规矩我们需要打一个断点来查看,这里主要是要看源码中是在什么时候执行后置处理器的回调

在这里插入图片描述

  1. 第一步createBean#doCreateBean(beanName, mbdToUse, args)(前面的一些先忽略)
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {

		// Instantiate the bean. 实例化Bean对象,注意这里只是对象,不是Bean
		......

		// Allow post-processors to modify the merged bean definition.
		......

		// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
		......

		// Initialize the bean instance.初始化Bean实例
		Object exposedObject = bean;
		try {
			//Bean对象属性赋值
			populateBean(beanName, mbd, instanceWrapper);
			//初始化Bean;这里可以看出,初始化Bean是在属性赋值之后进行的
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		......
		
		return exposedObject;
	}
  1. 第二步doCreateBean#initializeBean(beanName, exposedObject, mbd),从这段代码可以看出BeanPostProcessor的调用顺序
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
		......忽略

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
		//1、调用初始化前方法BeanPostProcessor#postProcessBeforeInitialization(result, beanName)
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
		//2、调用Bean初始化方法
			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()) {
		//3、调用初始化前方法BeanPostProcessor#postProcessAfterInitialization(result, beanName)
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}
		return wrappedBean;
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值