一、Bean 的生命周期

  对于普通的 Java 对象,new 的时候会去创建对象,而当它没有任何引用的时候则被垃圾回收机制回收。相较于前者,由Spring IoC 容器托管的对象,它们的生命周期完全由容器控制。Spring 中每个 Bean 的生命周期如下:
在这里插入图片描述

  • 对于 ApplicationContext 容器,当容器启动结束后,实例化所有的 Bean。
  • 设置对象属性,即依赖注入,动态将依赖关系注入到对象中。
  • 紧接着,Spring 会检测该对象是否实现了 xxxAware 接口,并将相关的 xxxAware实例注入给 Bean。
  • 当经过上述几个步骤后,Bean对象已经被正确构造,但如果你想要对象被使用前再进行一些自定义的处理,就可以通过
    BeanPostProcessor接口实现。

该接口提供了两个函数:

  1. postProcessBeforeInitialzation( Object bean, String beanName ) 当前正在初始化的 Bean 对象会被传递进来,我们就可以对这个 Bean 作任何处理。 这个函数会先于 InitialzationBean 执行,因此称为前置处理。 所有 Aware 接口的注入就是在这一步完成的。
  2. postProcessAfterInitialzation( Object bean, String beanName ) 当前正在初始化的 Bean 对象会被传递进来,我们就可以对这个 Bean 作任何处理。 这个函数会在 InitialzationBean 完成后执行,因此称为后置处理。
  • 当 BeanPostProcessor 的前置处理完成后就会进入以下阶段。
  • 这一阶段也可以在 Bean 正式构造完成前增加我们自定义的逻辑,但它与前置处理不同,由于该函数并不会把当前 Bean 对象传进来,因此在这一步没办法处理对象本身,只能增加一些额外的逻辑。 若要使用它,我们需要让 Bean 实现该接口,并把要增加的逻辑写在该函数中。然后 Spring 会在前置处理完成后检测当前 Bean 是否实现了该接口,并执行 afterPropertiesSet 函数。

InitializingBean 接口只有一个函数:afterPropertiesSet()

  • 当然,Spring为了降低对客户代码的侵入性,给bean的配置提供了 init-method 属性,该属性指定了在这一阶段需要执行的函数名。Spring便会在初始化阶段执行我们设置的函数。 init-method本质上仍然使用了InitializingBean接口。
  • 通过给 destroy-method 指定函数,就可以在 Bean 销毁前执行指定的逻辑。

二、代码演示

项目结构如下:(红框中为代码演示使用到)
在这里插入图片描述

创建启动入口类:org.example.AppLifecycle

package org.example;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AppLifecycle {

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("lifecycle.xml");
        ((ClassPathXmlApplicationContext) context).close();
    }
}

Spring配置文件:在src/main/resources下,创建lifecycle.xml文件

<?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
    https://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    https://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="org.example.config"/>
</beans>

准备要进行生命周期管理的Bean对象,创建org.example.model.LifeCycleTest

package org.example.config;

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

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

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

    public void beanInit(){
        System.out.println("init-method: 注解是使用@Bean(initMethod=\"方法名\")的方式,xml是使用<bean init-method=\"方法名\" />");
    }

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

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

    public void beanDestroy(){
        System.out.println("destroy-method: 注解是使用@Bean(destroyMethod=\"方法名\")的方式,xml是使用<bean destroy-method=\"方法名\" />");
    }

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

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

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

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

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

使用创建的配置类org.example.config.AppConfig

package org.example.config;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig implements BeanPostProcessor {

    @Bean(initMethod = "beanInit", destroyMethod = "beanDestroy")
    public LifeCycleTest lifeCycleTest(){
        return new LifeCycleTest();
    }

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

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

代码运行结果
在这里插入图片描述


三、主要步骤简述

  • 实例化 Bean:通过反射调用构造方法实例化对象。
  • 依赖注入:装配 Bean 的属性。
  • 实现了 Aware接口的 Bean,执行接口方法:如顺序执行 BeanNameAware、BeanFactoryAware、ApplicationContextAware的接口方法。
  • Bean 对象初始化前,循环调用实现了 BeanPostProcessor 接口的预初始化方法(postProcessBeforeInitialization)。
  • Bean 对象初始化:顺序执行 @PostConstruct 注解方法、InitializingBean 接口方法、init-method 方法。
  • Bean 对象初始化后,循环调用实现了 BeanPostProcessor 接口的后初始化方法(postProcessAfterInitialization)。
  • 容器关闭时,执行 Bean 对象的销毁方法,顺序是:@PreDestroy 注解方法、DisposableBean 接口方法、destroy-method。

补充说明:第一步的实例化是指new对象,Spring的语义中说初始化Bean包含Bean生命周期中的初始化步骤。


Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐