Spring Bean的生命周期

1,271 阅读3分钟

Spring Bean的生命周期

Bean的生命周期

SpringBean生命周期

图1 Bean生命周期流程图

1. 初始化Bean

容器通过获取BeanDefinition中的信息进行实例化,这一步仅仅是简单的实例化,并没有进行依赖注入。

实例化的对象被包装在BeanWrapper对象中,BeanWrapper提供了设置对象属性的接口,从而避免了使用反射机制来注入属性。

2. 设置对象属性(依赖注入)

实例化后的Bean仍是一个原生的状态,然后Spring根据BeanDefinition中的信息进行依赖注入,并且通过BeanWrapper提供的设置属性的接口完成依赖注入。

3. 注入Aware接口

Spring会检测该对象是否实现了xxxAware接口,并将相关的xxxAware实例注入给bean。

  • BeanNameAware:通过Bean的引用来获取Bean的ID,一般业务中很少使用;
  • BeanFactoryAware:获取Spring BeanFactory容器,如发布事件等;
  • ApplicationContextAwaer:获取Spring ApplicationContext容器;

4. BeanPostProcessor前置处理

如果Spring实现了BeanPostProcessor接口,pring将调用它们的postProcessBeforeInitialization(Object bean, String beanName)(预初始化)方法,作用是在Bean实例创建成功后对进行增强处理,如对Bean进行修改,增加某个功能。

5. InitializingBean接口

InitializingBean接口只有一个函数:afterPropertiesSet(),作用是在bean正式构造完成前增加我们自己自定义的逻辑,与前置处理不同,该函数的入参没有bean对象, 因为无法处理bean对象本身,只能增加一些额外的逻辑。

6. init-method声明

作用同InitializingBean接口。

7. BeanPostProcessor后置处理

如果Spring实现了BeanPostProcessor接口,pring将调用它们的postProcessAfterInitialization(Object bean, String beanName)(预初始化)方法,作用与4的一样,只不过6是在Bean初始化前执行的,而这个是在Bean初始化后执行的,时机不同。

8. Bean初始化完成

经过以上的工作后,Bean将一直驻留在应用上下文中给应用使用,直到应用上下文被销毁。

9. DispostbleBean接口

DispostbleBean接口只有一个函数:destroy(),在bean被销毁前执行此函数里的逻辑。

10. destroy-method声明

作用同DispostbleBean接口。

代码

person类实现了BeanNameAwareBeanFactoryAwareApplicationContextAwaerInitializingBeanDispostbleBean 接口。

package tech.mervyn.demo.entity;

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

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

    private String name;

    public Person() {
        System.out.println("调用默认构造器实例化对象...");
    }

    public void setName(String name) {
        System.out.println("调用Setter方法设置属性...");
        this.name = name;
    }

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("获取beanName -> " + name);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("获取BeanFactory -> " + beanFactory.hashCode());
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("获取applicationContext -> " + applicationContext.hashCode());
    }

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

    public void initMethod() {
        System.out.println("执行init-method声明逻辑...");
    }

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

    public void destroyMethod() {
        System.out.println("执行destroy-method声明逻辑...");
    }

}

自定义MyBeanPostProcessor类继承BeanPostProcessor并实现postProcessBeforeInitialization(Object bean, String beanName)postProcessAfterInitialization(Object bean, String beanName)方法。

package tech.mervyn.demo.processor;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("BeanPostProcessor前置处理," + beanName + " -> " + bean);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("BeanPostProcessor后置处理," + beanName + " -> " + bean);
        return bean;
    }
}

配置类

package tech.mervyn.demo.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import tech.mervyn.demo.entity.Person;
import tech.mervyn.demo.processor.MyBeanPostProcessor;

@Configuration
public class AppConfig {

    @Bean(initMethod = "initMethod", destroyMethod = "destroyMethod")
    public Person person() {
        Person person = new Person();
        person.setName("Mervyn");
        return person;
    }

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

}

执行

package tech.mervyn.demo;

import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import tech.mervyn.demo.config.AppConfig;

public class LiftCycleTests {

    @Test
    void liftCycle() {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        context.registerShutdownHook();
    }

}

输出,其中删除了一些无用日志:

22:29:54.047 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'appConfig'
22:29:54.052 [main] INFO org.springframework.context.support.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - Bean 'appConfig' of type [tech.mervyn.demo.config.AppConfig$$EnhancerBySpringCGLIB$$b60c41a9] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
22:29:54.072 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'person'
调用默认构造器实例化对象...
调用Setter方法设置属性...
获取beanName -> person
获取BeanFactory -> 1390913202
获取applicationContext -> 1297836716
BeanPostProcessor前置处理,person -> Person{name='Mervyn'}
执行InitializingBean逻辑...
执行init-method声明逻辑...
BeanPostProcessor后置处理,person -> Person{name='Mervyn'}
执行DisposableBean逻辑...
执行destroy-method声明逻辑...

注意,日志中有这样一行输出: org.springframework.context.support.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - Bean 'appConfig' of type [tech.mervyn.demo.config.AppConfig$$EnhancerBySpringCGLIB$$b60c41a9] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying),打印这行信息是由于BeanPostProcessor启动时对依赖的Bean造成误伤,具体原因有时间再讲。