Spring 框架中 Bean 的生命周期详解


Java
在 Spring 框架中,Bean 的生命周期是指从 Bean 的创建到销毁的整个过程,Spring 容器负责管理 Bean 的整个生命周期。


完整生命周期:实例化 -> 属性赋值 -> BeanPostProcessor 的前置处理 -> 初始化 -> BeanPostProcessor 的后置处理 -> 使用 -> 销毁。

在整个生命周期中,BeanPostProcessor 可以在初始化前后修改Bean的实例,为扩展和自定义Spring的行为提供了强大的功能。初始化和销毁方法可以通过多种方式指定,可以根据项目需求和编码风格选择合适的方式。

通过掌握Bean的生命周期,可以在不同阶段对Bean进行自定义操作,确保资源的正确使用和释放,以及利用 BeanPostProcessor 实现一些高级功能,如 AOP 代理等。理解Bean的生命周期有助于更好地管理Bean的创建、使用和释放资源,同时也有助于理解Spring框架的内部工作原理,为开发更健壮、可维护的Spring应用程序打下基础。

Spring 中 Bean 的生命周期

一、总结 Bean 生命周期的阶段

由上图可以看出,Spring Bean的生命周期可以分为以下几个阶段:

  1. 实例化:创建Bean实例。
  2. 属性赋值:注入依赖和配置。
  3. Aware接口回调:设置Bean名称、BeanFactory、ApplicationContext等。这里有三步。
  4. 初始化前处理BeanPostProcessorpostProcessBeforeInitialization(),也就是预初始化方法。
  5. 初始化@PostConstructInitializingBean.afterPropertiesSet()、自定义初始化方法。这里有两步。
  6. 初始化后处理BeanPostProcessorpostProcessAfterInitialization()
  7. 使用:Bean已准备好,可以被应用程序使用。
  8. 销毁@PreDestroyDisposableBean.destroy()、自定义销毁方法。
  9. 垃圾回收:Bean实例被回收。

二、分解 Bean 生命周期的阶段

01、实例化(Instantiation)

Spring容器根据配置信息(XML、注解或Java配置)创建Bean的实例。可以通过构造函数或者工厂方法来实例化Bean。对于采用默认构造函数创建Bean的情况,Spring会直接调用其构造函数创建实例;对于使用工厂方法创建Bean的情况,会调用工厂方法。

@Component
public class MyBean {
    public MyBean() {
        System.out.println("MyBean 实例化");
    }
}

当Spring容器启动时,会调用 MyBean 的无参构造函数进行实例化操作。

02、属性赋值(Populate Properties)

  • 触发时机:在实例化Bean之后。

在实例化Bean之后,Spring容器会将配置的属性值或依赖注入(Dependency Injection)到Bean的属性中。这可以通过 @Autowired@Resource 等注解,或者在XML配置文件中使用 <property> 元素来完成。

@Component
public class MyBean {
    @Autowired
    private AnotherBean anotherBean;

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

上面示例中 anotherBean 属性会在实例化 MyBean 之后被注入。

03、BeanNameAware.setBeanName()

  • 触发时机:属性赋值之后。

在属性赋值后,如果Bean实现了BeanNameAware接口,Spring会调用setBeanName()方法,传入 Bean 的 ID 或名称。

04、BeanFactoryAware.setBeanFactory()

  • 触发时机:setBeanName() 之后。

如果Bean实现了BeanFactoryAware接口,Spring会调用setBeanFactory()方法,传入 BeanFactory 实例。

05、ApplicationContextAware.setApplicationContext()

  • 触发时机:setBeanFactory() 之后。

如果Bean实现了 ApplicationContextAware 接口,Spring会调用 setApplicationContext() 方法,传入 ApplicationContext 实例。

06、前置处理:BeanPostProcessor.postProcessBeforeInitialization()

  • 触发时机:setApplicationContext() 之后,初始化之前。

如果存在 BeanPostProcessor,在调用初始化方法之前,会调用其 postProcessBeforeInitialization 方法。BeanPostProcessor 允许对Bean的实例进行修改,如包装或替换。

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof MyBean) {
            System.out.println("在 MyBean 初始化前处理");
        }
        return bean;
    }
}

MyBean 处于生命周期的这个阶段时,上述 MyBeanPostProcessor 会被调用,执行 postProcessBeforeInitialization 方法。

07、@PostConstruct 或 InitializingBean.afterPropertiesSet()

  • 触发时机:postProcessBeforeInitialization() 之后。

如果Bean使用了@PostConstruct注解,Spring会调用该注解标记的方法。
如果Bean实现了InitializingBean接口,Spring会调用afterPropertiesSet()方法。

08、自定义初始化方法(init-method)

  • 触发时机:afterPropertiesSet()@PostConstruct 之后。

如果Bean配置了自定义的初始化方法(通过XML的 init-method 属性或 @Bean(initMethod = "...") ),Spring会调用该方法,有多种方式可以指定Bean的初始化方法。

1、使用 @PostConstruct 注解:

@Component
public class MyBean {
    @PostConstruct
    public void init() {
        System.out.println("MyBean 初始化");
    }
}

2、实现 InitializingBean 接口:

@Component
public class MyBean implements InitializingBean {
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("MyBean 初始化");
    }
}

3、在XML配置文件中使用 init-method 属性:

<bean id="myBean" class="com.example.MyBean" init-method="initMethod">
</bean>

其中 initMethodMyBean 类中自定义的初始化方法。

09、后置处理:BeanPostProcessor.postProcessAfterInitialization(),

  • 触发时机:自定义初始化方法之后。

类似于前置处理,如果容器中有BeanPostProcessor,在初始化方法之后,会调用 BeanPostProcessorpostProcessAfterInitialization 方法。

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof MyBean) {
            System.out.println("在 MyBean 初始化后处理");
        }
        return bean;
    }
}

此时会对 MyBean 执行 postProcessAfterInitialization 操作。

10、Bean的使用

  • 触发时机:初始化完成后。

Bean已准备好,可以被应用程序使用。

11、@PreDestroy 或 DisposableBean.destroy()

  • 触发时机:容器关闭时。

1、如果Bean使用了 @PreDestroy 注解,Spring会在销毁前调用该注解标记的方法。

@Component
public class MyBean {
    @PreDestroy
    public void destroy() {
        System.out.println("MyBean 销毁");
    }
}

2、如果Bean实现了 DisposableBean 接口,Spring会调用 destroy() 方法。

@Component
public class MyBean implements DisposableBean {
    @Override
    public void destroy() throws Exception {
        System.out.println("MyBean 销毁");
    }
}

3、在XML配置文件中使用 destroy-method 属性。

<bean id="myBean" class="com.example.MyBean" destroy-method="destroyMethod">
</bean>

12、自定义销毁方法(destroy-method)

  • 触发时机:destroy()@PreDestroy 之后。

如果Bean配置了自定义的销毁方法(通过XML的destroy-method属性或@Bean(destroyMethod = "...")),Spring会调用该方法。

13、垃圾回收(Garbage Collection)

  • 触发时机:Bean销毁后。

Bean实例不再被引用,等待垃圾回收器回收。

三、整体示例代码

public class MyBean implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean, DisposableBean {

    private String name;

    public MyBean() {
        System.out.println("1. Instantiation: Constructor called");
    }

    public void setName(String name) {
        this.name = name;
        System.out.println("2. Populate Properties: setName called");
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("3. BeanNameAware: setBeanName called with " + name);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("4. BeanFactoryAware: setBeanFactory called");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("5. ApplicationContextAware: setApplicationContext called");
    }

    @PostConstruct
    public void postConstruct() {
        System.out.println("7. @PostConstruct: postConstruct called");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("8. InitializingBean: afterPropertiesSet called");
    }

    public void customInit() {
        System.out.println("9. Custom init-method: customInit called");
    }

    @PreDestroy
    public void preDestroy() {
        System.out.println("11. @PreDestroy: preDestroy called");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("12. DisposableBean: destroy called");
    }

    public void customDestroy() {
        System.out.println("13. Custom destroy-method: customDestroy called");
    }
}

配置示例:

<bean id="myBean" class="com.example.MyBean" init-method="customInit" destroy-method="customDestroy">
    <property name="name" value="MyBeanName"/>
</bean>
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值