SpringBean的生命周期

bean的生命周期

传统的java对象的生命周期很简单。使用new关键字创建一个对象,就可以使用了。当不再需要使用时,由Java虚拟机自动进行回收。

Spring中bean的生命周期相对要复杂很多。Spring在创建bean的过程中提供了很多扩展点来允许我们自定义bean的创建过程。

先看下面这张bean的生命周期图
在这里插入图片描述
上图截取至 《spring in action 》 这本书。详细的描述了bean在Spring容器中从创建到销毁经历的若干阶段。每一个阶段都可以针对Spring如何管理bean进行个性化定制。

对上图的流程进行详细的描述:

  1. Spring对bean进行实例化,即创建这个bean的一个对象;
  2. Spring将值和bean的引用注入到bean对应的属性中;
  3. 如果bean实现了BeanNameAware接口,Spring将bean的ID传递给setBeanName()方法;
  4. 如果bean实现了BeanFactoryAware接口,Spring将调用setBeanFactory()方法,将BeanFactory容器实例传入;
  5. 如果bean实现了ApplicationContextAware接口,Spring将调用setApplicationContext()方法,将bean所在的应用上下文的引用传进来;
  6. 如果bean实现了BeanPostProcesser接口,Spring将调用它们的postProcessBeforeInitialization()方法;
  7. 如果bean实现了InitializingBean接口,Spring将调用它们的afterPropertiesSet()方法。
  8. 如果bean实现了自己的init-method方法,则该方法被调用;
  9. 如果bean实现了BeanPostProcesser接口,Spring将调用它们的postProcessAfterInitialization()方法;
  10. 此时bean已经准备就绪,可以被程序使用,它们将一直驻留在应用上下文中,直到该应用上下文被销毁;
  11. 如果bean实现了DisposableBean 接口,Spring将调用它们的destroy()方法;
  12. 如果bean实现了自己的destroy-method方法,该方法被调用;

以上就是参考 《spring in action 》 这本书中描述的Spring容器中bean的生命周期过程,简单来说就是 创建-使用-销毁,在创建时你可以实现Spring提供的接口对创建过程进行干预,在销毁时也可以实现Spring提供的接口对销毁过程进行干预。

验证

下面编码验证

  1. 编写TestBean类,实现上述接口
public class TestBean implements BeanNameAware, BeanFactoryAware, ApplicationContextAware,InitializingBean,
        DisposableBean {

    private BeanFactory factory;

    private ApplicationContext applicationContext;

    public TestBean(){
        System.out.println("TestBean 类实例化...");
    }

    public void doSomething(){
        System.out.println("调用bean对象的业务方法 doSomething...");
    }

    @Override
    public void setBeanName(String s) {
        System.out.println("BeanNameAware接口的 setBeanName方法被调用,Bean的名称为:" + s);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.factory = beanFactory;
        System.out.println("BeanFactoryAware接口的 setBeanFactory方法被调用");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
        System.out.println("ApplicationContextAware接口的 setApplicationContext方法被调用");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean接口的 afterPropertiesSet方法被调用");
    }

    @PostConstruct
    public void postConstruct(){
        System.out.println("自定义的 postConstruct 方法被调用");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("DisposableBean接口的 destroy方法被调用");
    }

    @PreDestroy
    public void preDestroy(){
        System.out.println("自定义的 preDestroy 方法被调用");
    }

    public void initMethod(){
        System.out.println("自定义的 initMethod 方法被调用");
    }

    public void destroyMethod(){
        System.out.println("自定义的 destroyMethod 方法被调用");
    }
  1. 编写 BeanPostProcessor 接口实现类
public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization--实例化的bean对象:"+bean+"\t"+beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization...实例化的bean对象:"+bean+"\t"+beanName);
        return bean;
    }
}
  1. 编写配置类
@Configuration
public class TestConfig{

    @Bean
    public MyBeanPostProcessor myBeanPostProcessor(){
        return new MyBeanPostProcessor();
    }

    @Bean(initMethod = "initMethod",destroyMethod = "destroyMethod")
    public TestBean testBean(){
        return new TestBean();
    }
}
  1. 编写测试类
public class TestMain {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(TestConfig.class);
        TestBean testBean = annotationConfigApplicationContext.getBean(TestBean.class);
        testBean.doSomething();
        annotationConfigApplicationContext.close();
    }
}
  1. 执行结果
TestBean 类实例化...
BeanNameAware接口的 setBeanName方法被调用,Bean的名称为:testBean
BeanFactoryAware接口的 setBeanFactory方法被调用
ApplicationContextAware接口的 setApplicationContext方法被调用
postProcessBeforeInitialization--实例化的bean对象:com.demo.TestBean@77d67cf3	testBean
自定义的 postConstruct 方法被调用
InitializingBean接口的 afterPropertiesSet方法被调用
自定义的 initMethod 方法被调用
postProcessAfterInitialization...实例化的bean对象:com.demo.TestBean@77d67cf3	testBean
调用bean对象的业务方法 doSomething...
自定义的 preDestroy 方法被调用
DisposableBean接口的 destroy方法被调用
自定义的 destroyMethod 方法被调用

验证代码中添加了两个注解方法 @PostConstruct、@PreDestroy 这两个方法有时候经常被用来代替initMethod和destroyMethod方法使用

各接口的作用

  1. BeanNameAware
    该接口的实现方法只是简单的返回当前bean的名称,让当前bean知道它在容器中的名字。
  2. BeanFactoryAware
    该接口的实现方法返回当前容器的BeanFactory对象,可以用来手动注册 Bean。该对象的真实对象类型是 DefaultListableBeanFactory,调用它的 registerBeanDefinition(beanName, beanDefinition)方法可用手动注册Bean到容器中。
  3. ApplicationContextAware
    该接口的实现方法返回当前容器的上下文对象,该对象是比BeanFactory对象更高一级别的容器对象,也可以实现BeanFactory对象的各种功能。如上面的手动注册Bean。
  4. InitializingBean
    该接口的实现方法在bean的属性被填充后调用,即bean被创建完成后执行,然后我们可以在该方法中处理一些需要bean被实例化后才能做的事。比如网络连接,初始化一些资源等。该方法和initMethod方法、@PostConstruc注解方法经常替换使用。
  5. DisposableBean
    该接口的实现方法在bean被销毁的时候调用,经常用来释放一些资料等。通常和 destroyMethod方法、@PreDestroy注解方法替换使用。
  6. BeanPostProcessor
    该接口被称为Bean的后置处理器。有两个方法 postProcessBeforeInitialization()和postProcessAfterInitialization(),这两个方法的参数也一样。Before方法在初始化方法回调之前执行,可进行bean实例属性的填充等操作。After方法在初始化方法回调后执行,可以在该方法中对Bean对象做一些包装工作。

以上,是我个人的一点浅显理解,有错误或不足之处,请大家指正。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值