Spring—Bean的生命周期

引子

今天学习Spring中的Bean的生命周期。我们知道,Bean在Spring中可以说是重中之重、必不可少的东西。我对Bean的理解就像是一个个的对象,每个对象有自己的属性,这个对象中包含了与它相关的所有信息,就像是一个信息的集合体。控制反转(IOC)、依赖注入(DI)都和Bean有关系。我们需要了解的是Bean的定义和初始化在Spring IOC容器中是两大步骤,它是先定义,然后初始化和依赖注入的。

Bean的定义分为3步:

  • Resource定位,这步是Spring IOC容器根据开发中的配置,进行资源定位,在Spring的开发中,通过XML或者注解都是十分常见的方式,定位的内容是由开发者所提供的。
  • BeanDefinition的载入,这个时候只是将Resource定位到的信息,保存到Spring IOC容器中,注意,此时仍旧没有对应的Bean的实例创建。
  • BeanDefinition的注册,这个过程就是将BeanDefinition的信息发布到Spring IOC中,注意,此时仍旧没有对应的Bean的实例创建。

做完了这3步,Bean就在Spring IOC容器中被定义了,而没有被初始化,更没有完成依赖注入,也就是没有注入其配置的资源给Bean,那么它还不能完全使用。Spring Bean还有一个配置选项——lazy-init,其含义就是是否初始化Spring Bean。在没有任何配置的情况下,它的默认值为default,实际值为false,也就是Spring IOC默认会自动初始化Bean。如果将其设置为true,那么只有当我们使用Spring IOC容器的getBean方法获取它时,它才会进行Bean的初始化,完成依赖注入。

Spring的生命周期

Spring IOC容器的本质就是为了管理Bean。对于Bean而言,在容器中存在其生命周期,它的初始化和销毁也需要一个过程,在一些需要自定义的过程中,我们可以插入代码去改变它们的一些行为,以满足特定的需求,这就需要使用到Spring Bean生命周期了。

Spring IOC容器对Bean的管理还是比较复杂的,接下来详细说下生命周期的步骤:

  1. 如果Bean实现了接口BeanNameAwaresetBeanName方法,那么它就会调用这个方法。
  2. 如果Bean实现了接口BeanFactoryAwaresetBeanFactory方法,那么它就会调用这个方法。
  3. 如果Bean实现了接口ApplicationContextAwaresetApplicationContext方法,且Spring IOC容器也必须是一个ApplicationContext接口的实现类,那么才会调用这个方法,否则是不调用的。
  4. 如果Bean实现了接口BeanPostProcessorpostProcessBeforeInitialization方法,那么它就会调用这个方法。
  5. 如果Bean实现了接口BeanFactoryPostProcessorafterPropertiesSet方法,那么它就会调用这个方法。
  6. 如果Bean自定义了初始化方法,它就会调用已定义的初始化方法。
  7. 如果Bean实现了接口BeanPostProcessorpostProcessAfterInitialization方法,完成了这些调用,这个时候Bean就完成了初始化,那么Bean就生存在了Spring IOC的容器中了,使用者就可以从中获取Bean的服务。

当服务器正常关闭,或者遇到其他关闭Spring IOC容器的事件,它就会调用对应的方法完成Bean的销毁,其步骤如下:

  • 如果Bean定义了实现接口DisposableBeandestory方法,那么就会调用它。
  • 如果定义了自定义销毁方法,那么就调用它。

所有的Spring IOC容器最低的要求是实现BeanFactory接口,而不是ApplicationContext接口,如果采用了非ApplicationContext子类创建了Spring IOC容器,那么即使是实现了ApplicationContextAware的setApplicationContext方法,它也不会在生命周期之中被调用。

以下展示的是Bean可以实现的接口以及要实现的方法:

public class Bean_class_name implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean {
	//字段略
	//getter and setter
	
	/*
		这是自定义初始化方法,要在XML文件中配置init-method="方法名"
	*/
	public void init() {
		System.out.println("【" + this.getClass().getSimpleName() + "】执行自定义初始化方法");
	}
	
	/*
		这是自定义销毁方法,要在XML文件中配置destory-method="方法名"
	*/
	public void destroy() {
		System.out.println("【" + this.getClass().getSimpleName() + "】执行自定义销毁方法");
	}
	
	/*
		这是实现BeanNameAware接口,要实现其中的setBeanName方法。
	*/
	@Override
	public void setBeanName(String arg0) {
		System.out.println("【" + this.getClass().getSimpleName() + "】调用BeanNameAware接口的setBeanName方法");

	}

	/*
		这是实现BeanFactoryAware接口,要实现其中的setBeanFactory方法。
	*/
	@Override
	public void setBeanFactory(BeanFactory arg0) throws BeansException {
		System.out.println("【" + this.getClass().getSimpleName() + "】调用BeanFactoryAware接口的setBeanFactory方法");
	}

	/*
		这是实现ApplicationContextAware接口,要实现其中的setApplicationContext方法。
	*/
	@Override
	public void setApplicationContext(ApplicationContext arg0) throws BeansException {
		System.out.println(
				"【" + this.getClass().getSimpleName() + "】调用ApplicationContextAware接口的setApplicationContext方法");
	}

	/*
		这是实现InitializingBean接口,要实现其中的afterPropertiesSet方法。
	*/
	@Override
	public void afterPropertiesSet() throws Exception {
		System.out.println("【" + this.getClass().getSimpleName() + "】调用InitializingBean接口的afterPropertiesSet方法");
	}
}

注意,上述生命周期的接口,大部分是针对单个Bean而言的,BeanPostProcessor接口则是针对所有Bean而言的

public class BeanPostProcessorImpl implements BeanPostProcessor {

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		System.out.println("【" + bean.getClass().getSimpleName() + "】对象" + beanName + "开始实例化");
		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		System.out.println("【" + bean.getClass().getSimpleName() + "】对象" + beanName + "实例化完成");
		return bean;
	}

}

这样一个BeanPostProcessor就被我们用代码实现了,它会处理Spring IOC容器所有的Bean。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值