Spring 教程

Spring 笔记

Spring Bean 生命周期


理解 Spring bean 的生命周期很容易。当一个 bean 被实例化时,它可能需要执行一些初始化使它转换成可用状态。同样,当 bean 不再需要,并且从容器中移除时,可能需要做一些清除工作。

生命周期流程图

Spring Bean 的完整生命周期从创建 Spring 容器开始,直到最终 Spring 容器销毁 Bean,这其中包含了一系列关键点。

示例

创建两个 bean,让其相互依赖。

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;

public class BeanADemo implements ApplicationContextAware, BeanFactoryAware, BeanNameAware, BeanPostProcessor, DisposableBean, InitializingBean {

    private BeanBDemo beanBDemo;

    public BeanADemo() {
        System.out.println("Constructor BeanADemo invoked");
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("setBeanName " + name + " invoked");
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("setBeanFactory invoked");
    }

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

    @PostConstruct
    public void postConstructMethod() {
        System.out.println("Post Construct BeanADemo invoked");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean afterPropertiesSet BeanADemo invoked");
    }

    public void initMethod() {
        System.out.println("init-method BeanADemo invoked");
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("BeanPostProcessor postProcessBeforeInitialization BeanADemo invoked");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("BeanPostProcessor postProcessAfterInitialization BeanADemo invoked");
        return bean;
    }

    @PreDestroy
    public void preDestroyMethod() {
        System.out.println("Pre Destroy BeanADemo invoked");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("DisposableBean destroy BeanADemo invoked");
    }

    public void destroyMethod() {
        System.out.println("destroy-method BeanADemo invoked");
    }

    @Resource
    public void setBeanBDemo(BeanBDemo beanBDemo) {
        System.out.println("setBeanBDemo invoked");
        this.beanBDemo = beanBDemo;
    }
}
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;

public class BeanBDemo implements ApplicationContextAware, BeanFactoryAware, BeanNameAware, BeanPostProcessor, DisposableBean, InitializingBean {

    private BeanADemo beanADemo;

    public BeanBDemo() {
        System.out.println("Constructor BeanBDemo invoked");
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("setBeanName " + name + " invoked");
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("setBeanFactory B invoked");
    }

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

    @PostConstruct
    public void postConstructMethod() {
        System.out.println("Post Construct BeanBDemo invoked");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean afterPropertiesSet BeanBDemo invoked");
    }

    public void initMethod() {
        System.out.println("init-method BeanBDemo invoked");
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("BeanPostProcessor postProcessBeforeInitialization BeanBDemo invoked");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("BeanPostProcessor postProcessAfterInitialization BeanBDemo invoked");
        return bean;
    }

    @PreDestroy
    public void preDestroyMethod() {
        System.out.println("Pre Destroy BeanBDemo invoked");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("DisposableBean destroy BeanBDemo invoked");
    }

    public void destroyMethod() {
        System.out.println("destroy-method BeanBDemo invoked");
    }

    @Resource
    public void setBeanADemo(BeanADemo beanADemo) {
        System.out.println("setBeanADemo invoked");
        this.beanADemo = beanADemo;
    }
}

通过 xml 配置 bean。 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 开启基于注解的配置 -->
    <context:annotation-config/>

    <bean class="demo.BeanADemo" init-method="initMethod" destroy-method="destroyMethod"/>

    <bean class="demo.BeanBDemo" init-method="initMethod" destroy-method="destroyMethod"/>

</beans>

启动 Spring 容器及关闭。

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Demo {

    public static void main(String[] args) {

        ClassPathXmlApplicationContext ct = new ClassPathXmlApplicationContext("demo.xml");
        ct.close();
    }

}

执行结果如下:

Constructor BeanADemo invoked
Constructor BeanBDemo invoked
setBeanADemo invoked
setBeanName demo.BeanBDemo#0 invoked
setBeanFactory B invoked
ApplicationContextAware setApplicationContext invoked
Post Construct BeanBDemo invoked
InitializingBean afterPropertiesSet BeanBDemo invoked
init-method BeanBDemo invoked
setBeanBDemo invoked
setBeanName demo.BeanADemo#0 invoked
setBeanFactory invoked
ApplicationContextAware setApplicationContext invoked
Post Construct BeanADemo invoked
InitializingBean afterPropertiesSet BeanADemo invoked
init-method BeanADemo invoked
BeanPostProcessor postProcessBeforeInitialization BeanADemo invoked
BeanPostProcessor postProcessBeforeInitialization BeanBDemo invoked
BeanPostProcessor postProcessAfterInitialization BeanADemo invoked
BeanPostProcessor postProcessAfterInitialization BeanBDemo invoked
BeanPostProcessor postProcessBeforeInitialization BeanADemo invoked
BeanPostProcessor postProcessBeforeInitialization BeanBDemo invoked
BeanPostProcessor postProcessAfterInitialization BeanADemo invoked
BeanPostProcessor postProcessAfterInitialization BeanBDemo invoked
Pre Destroy BeanBDemo invoked
DisposableBean destroy BeanBDemo invoked
destroy-method BeanBDemo invoked
Pre Destroy BeanADemo invoked
DisposableBean destroy BeanADemo invoked
destroy-method BeanADemo invoked

可以得知,Spring IoC 容器中 bean 的初始化,首先调用所有 bean 的构造器,然后针对一个 bean 进行相应的初始化顺序,具体如下:

初始化时:构造器 Construct -> 属性注入 -> BeanNameAware 接口实现方法 -> BeanFactoryAware 接口实现方法 -> ApplicationContextAware 接口实现方法 -> @PostConstruct -> InitializingBean 接口实现方法 -> bean 定义的 initMethod;

销毁时:@PreDestroy -> DisposableBean 接口实现方法 -> bean 定义的 destoryMethod。