Spring中Bean的生命周期

Bean生命周期:

Bean的创建-----初始化-----销毁的过程(具体细节可以查看博客 Spring IOC源码解析

  1. 实例化bean:反射的方式生成对象
  2. 填充bean的属性:populateBean(),循环依赖的问题(三级缓存)
  3. 调用aware接口相关的方法:invokeAwareMethod(完成BeanName, BeanFactory, BeanClassLoader 对象的属性设置)
  4. 调用BeanPostProcessor中的前置处理方法:使用比较多的有(ApplicationContextPostProcessor, 设置ApplicationContext, Environment, ResourceLoader, EmbeddValueResolver 等对象)
  5. 调用initmethod方法:invokeInitmethod(),判断是否实现了initializingBean接口,如果有,调用afterPropertiesSet方法,没有就不调用
  6. 调用BeanPostProcessor的后置处理方法:spring的aop就是在此处实现的,AbstractAutoProxyCreator 。注册Destuction相关的回调接口:钩子函数
  7. 获取到完整的对象,可以通过getBean的方式来进行对象的获取
  8. 销毁流程: 
    1. 判断是否实现了DispoableBean接口
    2. 调用destroyMethod方法

1、@Bean注解指定初始化和销毁方法

@Bean(initMethod="initMethod" ,destoryMethod="destoryMethod")

@Scope("singleton")
@Bean(name = "person", initMethod = "initM" , destroyMethod = "destoryM") 
public Person person(){
	return new Person();
}

public class Person {

	public Person(){
		System.out.println("create Person");
	}
	
	public void initM(){
		System.out.println("init Method initM");
	}
	
	public void destoryM(){
		System.out.println("destory method destoryM");
	}
		
}

测试:

	@Test
	public void test2() throws InterruptedException{
		AnnotationConfigApplicationContext application = new AnnotationConfigApplicationContext(SpringCondiguration.class);
		System.out.println("容器启动"); 
                Thread.sleep(1000); 
		System.out.println("容器关闭");
		application.close();
	}

输出结果:

可以看出,容器在启动时就创建了bean实例,容器关闭时销毁bean实例。但是需要有个前提是bean单例的,且不是懒加载模式。如果抛开懒加载模式,仅论单例和多实例模式:

  • 单例模式下,容器启动时创建并初始化bean,容器关闭时销毁bean
  • 多实例模式,容器启动时创建不创建bean,仅在bean被调用时创建和初始化bean,且不管理bean的销毁,即容器关闭时不会销毁bean。
	@Scope("prototype")   
	@Bean(name = "person", initMethod = "initM" , destroyMethod = "destoryM") 
	public Person person(){
		return new Person();
	}


	@Test
	public void test2() throws InterruptedException{
		AnnotationConfigApplicationContext application = new AnnotationConfigApplicationContext(SpringCondiguration.class);
		System.out.println("容器启动"); 		
        Thread.sleep(1000); 
        Object person = application.getBean("person");
		System.out.println("容器关闭");
		application.close();
	}

输出结果:

2、InitiallizingBean、DisposableBean初始化和销毁接口

  • 实现IniitalizingBean接口重写afterPropertiesSet方法,bean创建时会自动调用该方法初始化bean。
  • 实现DisposableBean接口,重写destory方法,bean销毁前会调用该方法。
@Bean
public Person person(){
	return new Person();
}

public class Person implements InitializingBean , DisposableBean {

	public Person(){
		System.out.println("create Person");
	}

	public void afterPropertiesSet() throws Exception {
		System.out.println("afterPropertiesSet");
	}
	
	public void destroy() throws Exception {
		System.out.println("destroy");
	}	
}

测试:

	@Test
	public void test2(){
		AnnotationConfigApplicationContext application = new AnnotationConfigApplicationContext(SpringCondiguration.class);
		System.out.println("容器启动"); 		  
		System.out.println("容器关闭");
		application.close();
	}

输出结果:

3、JSR250规范中的注解

  • @PostConstruct  用于初始化方法,在bean创建完成后执行该注解标注的方法;
  • @PreDestroy  用于销毁方法,bean销毁前执行该方法
public class Person{

	public Person(){
		System.out.println("create Person");
	}

	@PostConstruct
	@PreDestroy
	public void afterPropertiesSet() throws Exception {
		System.out.println("afterPropertiesSet");
	} 	
}

4、BeanPostProcessor接口

BeanPostProcessor后置处理器,用于Bean的实例化、配置和其他的初始化前后添加一些自己的逻辑处理,

public interface BeanPostProcessor {
	
    //在bean初始化之前调用该方法,参数bean是带处理的实例bean,返回值Object是处理完成后的bean
	Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
    
    //bean初始化之后调用该方法
	Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

}

定义一个类实现该接口,重写两个抽象方法,并将该类注入实例,则该类将对Spring容器中所有的bean起作用。

定义一个MyBeanPostProcessor 类实现BeanPostProcessor :

public class MyBeanPostProcessor implements BeanPostProcessor {

	public Object postProcessBeforeInitialization(Object bean, String beanName)
			throws BeansException {
		System.out.println("before bean initMethod:  "+bean.getClass().getName() + "   beanName = "+beanName);
		return bean;
	}

	public Object postProcessAfterInitialization(Object bean, String beanName)
			throws BeansException {
		System.out.println("after bean initMethod:  "+bean.getClass().getName() + "   beanName = "+beanName);
		return bean;
	}
}

配置类和测试类:

@Configuration
public class SpringCondiguration {	 
	@Bean
	public Person person(){
		return new Person();
	}	
		
	@Bean
	public MyBeanPostProcessor bookFactoryBean(){
		return new MyBeanPostProcessor();
	}			
}


public class Person {
	
	public Person(){
		System.out.println("create person");
	}
	
	@PostConstruct
	public void afterPropertiesSet() throws Exception {
		System.out.println("person init");
	}
	
	@PreDestroy
	public void destroy() throws Exception {
		System.out.println("destroy");
	}	
}

测试:

	@Test
	public void test2(){
		AnnotationConfigApplicationContext application = new AnnotationConfigApplicationContext(SpringCondiguration.class); 
	}

输出结果:

从输出结果可以看出Spring创建Person实例时方法的调用顺序:Person的构造方法------->postProcessBeforeInitialization------>初始化方法 ------->postProcessAfterInitialization。而且,我们手动注入到容器中的bean只有Person和MyBeanPostProcessor,而MyBeanPostProcessor的作用范围包含了Spring自己定义的bean。

BeanPostProcessor在Spring中的应用非常广泛,后续会有专门的章节介绍Spring中对该接口的应用和原理。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值