乐趣区

关于java:大厂高频面试题Spring-Bean生命周期最详解

Spring 作为以后 Java 最风行、最弱小的轻量级框架。Spring Bean 的生命周期也是面试高频题,理解 Spring Bean 周期也能更好地帮忙咱们解决日常开发中的问题。程序员应该都晓得 Spring 的根底容器是 ApplicationContext。应很多粉丝的强烈建议,本文我来剖析剖析 ApplicationContext 中 Bean 的生命周期。ApplicationContext 是顶层容器接口 BeanFactory 的实现类,因而,咱们理解了 ApplicationContext 的生命周期逻辑,也基本上理解了其余类型容器的生命周期逻辑。

1 Spring 生命周期流程图

上面先来看一张 Spring Bean 残缺的生命周期流程图,下图形容的是从 Spring 容器初始化 Bean 开始直到 Spring 容器销毁 Bean,所经验的要害节点。

从上图能够看出,Spring Bean 的生命周期治理的基本思路是:在 Bean 呈现之前,先筹备操作 Bean 的 BeanFactory,而后操作完 Bean,所有的 Bean 也还会交给 BeanFactory 进行治理。在所有 Bean 操作筹备 BeanPostProcessor 作为回调。在 Bean 的残缺生命周期治理过程中,经验了以下次要几个步骤:

1.1 Bean 创立前的筹备阶段

步骤 1:Bean 容器在配置文件中找到 Spring Bean 的定义以及相干的配置,如 init-method 和 destroy-method 指定的办法。
步骤 2:实例化回调相干的后置处理器如 BeanFactoryPostProcessor、BeanPostProcessor、InstantiationAwareBeanPostProcessor 等

1.2 创立 Bean 的实例

步骤 3:Srping 容器应用 Java 反射 API 创立 Bean 的实例。
步骤 4:扫描 Bean 申明的属性并解析。

1.3 开始依赖注入

步骤 5:开始依赖注入,解析所有须要赋值的属性并赋值。
步骤 6:如果 Bean 类实现 BeanNameAware 接口,则将通过传递 Bean 的名称来调用 setBeanName() 办法。
步骤 7:如果 Bean 类实现 BeanFactoryAware 接口,则将通过传递 BeanFactory 对象的实例来调用 setBeanFactory() 办法。
步骤 8:如果有任何与 BeanFactory 关联的 BeanPostProcessors 对象已加载 Bean,则将在设置 Bean 属性之前调用 postProcessBeforeInitialization() 办法。
步骤 9:如果 Bean 类实现了 InitializingBean 接口,则在设置了配置文件中定义的所有 Bean 属性后,将调用 afterPropertiesSet() 办法。

1.4 缓存到 Spring 容器

步骤 10:如果配置文件中的 Bean 定义蕴含 init-method 属性,则该属性的值将解析为 Bean 类中的办法名称,并将调用该办法。
步骤 11:如果为 Bean Factory 对象附加了任何 Bean 后置处理器,则将调用 postProcessAfterInitialization() 办法。

1.5 销毁 Bean 的实例

步骤 12:如果 Bean 类实现 DisposableBean 接口,则当 Application 不再须要 Bean 援用时,将调用 destroy() 办法。
步骤 13:如果配置文件中的 Bean 定义蕴含 destroy-method 属性,那么将调用 Bean 类中的相应办法定义。

2 代码实战演示

上面咱们用一个简略的 Bean 来演示并察看一下 Spring Bean 残缺的生命周期。

2.1 筹备 Author 类

1、首先是一个简略的 Bean,调用 Bean 本身的办法和 Bean 级生命周期接口办法,为了不便演示,它实现了 BeanNameAware、BeanFactoryAware、InitializingBean 和 DiposableBean 这 4 个接口,同时增加 2 个 init-method 和 destory-method 办法,对应配置文件中 <bean> 的 init-method 和 destroy-method。具体代码如下:


package com.tom.lifecycle;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;

@Slf4j
@Data
public class Author implements BeanFactoryAware, BeanNameAware, InitializingBean, DisposableBean {
    private String name;
    private String address;
    private int age;

    private BeanFactory beanFactory;

    private String beanName;

    public Author() {log.info("【结构器】调用 Tom 类的结构器实例化");
    }

    public void setName(String name) {log.info("【注入属性】name");
        this.name = name;
    }

    public void setAddress(String address) {log.info("【注入属性】address");
        this.address = address;
    }

    public void setAge(int age) {log.info("【注入属性】age");
        this.age = age;
    }

    // 实现 BeanFactoryAware 接口的办法
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {log.info("【BeanFactoryAware 接口】调用 setBeanFactory 办法");
        this.beanFactory = beanFactory;
    }

    // 实现 BeanNameAware 接口的办法
    public void setBeanName(String beanName) {log.info("【BeanNameAware 接口】调用 setBeanName 办法");
        this.beanName = beanName;
    }

    // 实现 DiposibleBean 接口的办法
    public void destroy() throws Exception {log.info("【DiposibleBean 接口】调用 destroy 办法");
    }

    // 实现 InitializingBean 接口的办法
    public void afterPropertiesSet() throws Exception {log.info("【InitializingBean 接口】调用 afterPropertiesSet 办法");
    }

    // 通过 <bean> 的 init-method 属性指定的初始化办法
    public void beanInit() {log.info("【init-method】调用 <bean> 的 init-method 属性指定的初始化办法");
    }

    // 通过 <bean> 的 destroy-method 属性指定的初始化办法
    public void beanDestory() {log.info("【destroy-method】调用 <bean> 的 destroy-method 属性指定的初始化办法");
    }
}

在配置 Spring 配置文件中退出如下内容:


    <bean id="author" class="com.tom.lifecycle.Author"
          init-method="beanInit"
          destroy-method="beanDestory"
          scope="singleton"
          p:name="Tom" p:address="湖南长沙" p:age="18"/>
            

2.2 演示 BeanFactoryPostProcessor 的执行

1. 创立 GPBeanFactoryPostProcessor 类,并实现 BeanFactoryPostProcessor 接口,具体代码如下:


package com.tom.lifecycle;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;

@Slf4j
public class GPBeanFactoryPostProcessor implements BeanFactoryPostProcessor{public GPBeanFactoryPostProcessor() {super();
        log.info("调用 BeanFactoryPostProcessor 实现类结构器!!");
    }

    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {log.info("BeanFactoryPostProcessor 调用 postProcessBeanFactory 办法");
        BeanDefinition bd = configurableListableBeanFactory.getBeanDefinition("author");
        bd.getPropertyValues().addPropertyValue("age", "16");
    }
}

2. 在配置 Spring 配置文件中退出如下内容:


    <bean id="beanFactoryPostProcessor" class="com.tom.lifecycle.GPBeanFactoryPostProcessor" />

3. 编写测试类 BeanLifeCycleTest,具体代码如下:


package com.tom.lifecycle;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

@Slf4j
public class BeanLifeCycleTest {public static void main(String[] args) {log.info("====== 开始初始化 Spring 容器 ========");

        ApplicationContext factory = new ClassPathXmlApplicationContext("application-beans.xml");

        log.info("====== 初始化 Spring 容器胜利 ========");

        // 获取 Author 实例
        Author author = factory.getBean("author", Author.class);

        log.info(author.toString());

        log.info("====== 开始销毁 Spring 容器 ========");

        ((ClassPathXmlApplicationContext) factory).registerShutdownHook();}

}

4. 运行后果

运行后果如下:


15:49:12.477 [main] INFO com.tom.lifecycle.GPBeanPostProcessor - 调用 BeanPostProcessor 实现类结构器!!15:49:12.494 [main] INFO com.tom.lifecycle.Author -【结构器】调用 Tom 类的结构器实例化
15:49:12.527 [main] INFO com.tom.lifecycle.Author -【注入属性】address
15:49:12.528 [main] INFO com.tom.lifecycle.Author -【注入属性】age
15:49:12.528 [main] INFO com.tom.lifecycle.Author -【注入属性】name
15:49:12.528 [main] INFO com.tom.lifecycle.Author -【BeanNameAware 接口】调用 setBeanName 办法
15:49:12.528 [main] INFO com.tom.lifecycle.Author -【BeanFactoryAware 接口】调用 setBeanFactory 办法
15:49:12.528 [main] INFO com.tom.lifecycle.GPBeanPostProcessor - BeanPostProcessor 接口办法 postProcessBeforeInitialization 对属性进行更改
15:49:12.528 [main] INFO com.tom.lifecycle.Author -【InitializingBean 接口】调用 afterPropertiesSet 办法
15:49:12.528 [main] INFO com.tom.lifecycle.Author -【init-method】调用 <bean> 的 init-method 属性指定的初始化办法
15:49:12.528 [main] INFO com.tom.lifecycle.GPBeanPostProcessor - BeanPostProcessor 接口办法 postProcessAfterInitialization 对属性进行更改
15:49:12.531 [main] INFO com.tom.lifecycle.BeanLifeCycleTest - ====== 初始化 Spring 容器胜利 ========
15:49:12.531 [main] INFO com.tom.lifecycle.BeanLifeCycleTest - Author(name=Tom, address= 湖南长沙, age=18, beanFactory=org.springframework.beans.factory.support.DefaultListableBeanFactory@26653222: defining beans [beanPostProcessor,author]; root of factory hierarchy, beanName=author)
15:49:12.531 [main] INFO com.tom.lifecycle.BeanLifeCycleTest - ====== 开始销毁 Spring 容器 ========
15:49:12.532 [Thread-0] INFO com.tom.lifecycle.Author -【DiposibleBean 接口】调用 destroy 办法
15:49:12.533 [Thread-0] INFO com.tom.lifecycle.Author -【destroy-method】调用 <bean> 的 destroy-method 属性指定的初始化办法

咱们看到,整个执行和咱们一开始绘制的流程图统一。然而为什么咱们要实现 BeanFactoryPostProcessor 接口呢?咱们进入到 BeanFactoryPostProcessor 的源码如下:


package org.springframework.beans.factory.config;

import org.springframework.beans.BeansException;

public interface BeanFactoryPostProcessor {void postProcessBeanFactory(ConfigurableListableBeanFactory var1) throws BeansException;
}

BeanFactoryPostProcessor 接口只有一个 postProcessBeanFactory() 办法,BeanFactoryPostProcessor:在 BeanFactory 规范初始化之后能够进行批改。将加载所有 Bean 定义,然而还没有实例化 Bean。这个办法容许从新笼罩或者增加属性甚至疾速的初始化 bean。首次看到可能不晓得 postProcessBeanFactory() 到底是干嘛的。要想透彻了解这个办法的作用,上面来进入到 BeanFactoryPostProcessor 的源码,了解一下 postProcessBeanFactory() 的参数,咱们能够利用这些参数做一些操作。

通过参数来看,只有一个 ConfigurableListableBeanFactory 类,这个类的能够提供剖析、批改 Bean 定义和事后实例化单例的性能。咱们再进入到 ConfigurableListableBeanFactory 的源码中:


public interface ConfigurableListableBeanFactory extends ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory {

        // 疏忽被给定注入依赖类型,例如 String
    void ignoreDependencyType(Class<?> var1);

        // 略被给定注入依赖接口。这个通常被应用由 ApplicationContext 去注册依赖,能够以多种形式实现。例如 BeanFactory 通过 BeanFactoryAware,ApplicationContext 通过 ApplicationContextAware。默认状况下,仅 BeanFactoryAware 接口是被疏忽,须要疏忽其余接口,调用此办法
    void ignoreDependencyInterface(Class<?> var1);

        // 注册一个特定类型依赖随同着相应的 Autowired 值。这个是筹备被用于应该能够 Autowire 而不是在这个工厂被定义的 Bean 的工厂 / 上下文援用。例如 将 ApplicationContext 类型的依赖项解析为 Bean 所在的 ApplicationContext 实例。留神~ 在一般的 BeanFactory 中没有注册这样的默认类型,甚至连 BeanFactory 接口自身都没有
    void registerResolvableDependency(Class<?> var1, Object var2);

        // 确认这个被指定的 Bean 是否是一个 Autowire 候选,将被注入到其余申明匹配类型的依赖的 Bean 中
    boolean isAutowireCandidate(String var1, DependencyDescriptor var2) throws NoSuchBeanDefinitionException;

        // 依据指定的 beanName 返回被注册的 Bean 定义,容许拜访其属性值和构造函数参数值(能够在 BeanFactory 前期解决期间被批改)。这个被返回的 BeanDefinition 对象不应该是正本而是原始在工厂被注册的。这意味着如果须要它能够被转换为更具体的实现类型。留神这个办法只能取得本地工厂 BeanDefinition
    BeanDefinition getBeanDefinition(String var1) throws NoSuchBeanDefinitionException;

        // 解冻全副 Bean 定义,给被注册的 Bean 定义发信号通知它们今后不再被批改和进一步后续解决。它容许 Factory 去踊跃缓存 Bean 定义元数据
    void freezeConfiguration();

        // 返回该工厂的 BeanDefinnition 是否被解冻
    boolean isConfigurationFrozen();

        // 确保所有非懒加载的单例 Bean 被实例化,包含 FactoryBean
    void preInstantiateSingletons() throws BeansException;}

通过以上演示和剖析,咱们应该大略可能理解 ConfigurableListableBeanFactory 的作用,根本就都是对于 Bean 定义的操作。至此咱们还没有看到 BeanPostProcessor 和 InstantiationAwareBeanPostProcessor 的调用。上面咱们把 BeanPostProcessor 和 InstantiationAwareBeanPostProcessor 的实现补充上来,再看残缺的执行流程

2.3 实现 BeanPostProcessor

创立 GPBeanPostProcessor 类,并实现 BeanPostProcessor 接口,具体代码如下:


package com.tom.lifecycle;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

@Slf4j
public class GPBeanPostProcessor implements BeanPostProcessor {public GPBeanPostProcessor(){log.info("调用 BeanPostProcessor 实现类结构器!!");
    }
    public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {log.info("BeanPostProcessor 接口办法 postProcessBeforeInitialization 对属性进行更改");
        return o;
    }

    public Object postProcessAfterInitialization(Object o, String s) throws BeansException {log.info("BeanPostProcessor 接口办法 postProcessAfterInitialization 对属性进行更改");
        return o;
    }
}

ApplicationContext 能够在 BeanDefinition 中自动检测到实现了 BeanPostProcessor 的 Bean,并且把这些 Bean 利用于随后的 Bean 创立。一般的 BeanFactory 容许对后处理器进行程序化注册,通过工厂利用于所有 Bean 创立。BeanPostProcessor 接口中次要有两个办法:

办法名 解释
postProcessBeforeInitialization 在 Bean 实例化回调(例如 InitializingBean 的 afterPropertiesSet 或者一个定制的 init-method)之前利用此 BeanPostProcessor
postProcessAfterInitialization 在 bean 实例化回调(例如 InitializingBean 的 afterPropertiesSet 或者一个定制的 init-method)之后利用此 BeanPostProcessor

2.4 实现 InstantiationAwareBeanPostProcessor

创立 GPInstantiationAwareBeanPostProcessor 类,并实现 InstantiationAwareBeanPostProcessorAdapter 接口,具体代码如下:


package com.tom.lifecycle;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;

import java.beans.PropertyDescriptor;

@Slf4j
public class GPInstantiationAwareBeanPostProcessor  extends InstantiationAwareBeanPostProcessorAdapter {public GPInstantiationAwareBeanPostProcessor() {super();
        log.info("调用 InstantiationAwareBeanPostProcessorAdapter 实现类结构器!!");
    }

    // 接口办法、实例化 Bean 之前调用
    @Override
    public Object postProcessBeforeInstantiation(Class beanClass,String beanName) throws BeansException {log.info("InstantiationAwareBeanPostProcessor 调用 postProcessBeforeInstantiation 办法");
        return null;
    }

    // 接口办法、实例化 Bean 之后调用
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {log.info("InstantiationAwareBeanPostProcessor 调用 postProcessAfterInitialization 办法");
        return bean;
    }

    // 接口办法、设置某个属性时调用
    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {log.info("InstantiationAwareBeanPostProcessor 调用 postProcessPropertyValues 办法");
        return pvs;
    }
}

实现 InstantiationAwareBeanPostProcessorAdapter 的 Bean 之后,能够在实例化胜利之后,做一些校验或者补充些内容或者把 Bean 包装代理注入。实现 InstantiationAwareBeanPostProcessorAdapter 的 Bean 之后,不会影响容器失常解决每一个实例化的 Bean,其子类仅仅只是依据须要笼罩父类的办法。

留神,只有在理论须要 InstantiationAwareBeanPostProcessor 性能时才举荐此基类。如果咱们所须要的只是简略的 BeanPostProcessor 性能,那么间接实现更简略的接口即可。

上面具体介绍一下 InstantiationAwareBeanPostProcessorAdapter 接口中的所有办法:

办法名 解释
postProcessBeforeInstantiation 在实例化指标 Bean 之前利用此 BeanPostProcessor。这个返回的 Bean 兴许是一个代理代替指标 Bean,无效地克制指标 Bean 的默认实例化。如果此办法返回一个非空对象,则 Bean 的创立过程将被短路。惟一的进一步解决被利用是 BeanPostProcessor.postProcessAfterInitialization(java.lang.Object, java.lang.String) 办法(扭转了 Bean 的生命周期实例化之后间接进入 BeanPostProcessor.postProcessAfterInitialization)回调来自于配置好的 BeanPostProcessors。这个回调将仅被利用于有 Bean Class 的 BeanDefintions。特地是,它不会利用于采纳”factory-method“的 Bean。后处理器能够实现扩大的 SmartInstantiationAwareBeanPostProcessor 接口,以便预测它们将返回的 Bean 对象的类型
postProcessPropertyValues 在工厂将给定的属性值利用到给定的 Bean 之前,对给定的属性值进行后处理。容许查看全副依赖是否曾经全副满足,例如基于一个 @Required 在 Bean 属性的 Setter 办法上。还容许替换要利用的属性值,通常通过基于原始的 PropertyValues 创立一个新的 MutablePropertyValues 实例,增加或删除特定的值
postProcessAfterInitialization 在 Bean 初始化回调(如 InitializingBean 的 afterPropertiesSet 或者定制的 init-method)之后,利用这个 BeanPostProcessor 去给一个新的 Bean 实例。Bean 曾经配置了属性值,返回的 Bean 实例可能曾经被包装。<br/> 如果是 FactoryBean,这个回调将为 FactoryBean 实例和其余被 FactoryBean 创立的对象所调用。这个 post-processor 能够通过相应的 FactoryBean 实例去查看决定是否利用 FactoryBean 或者被创立的对象或者两个都有。这个回调在一个由 InstantiationAwareBeanPostProcessor 短路的触发之后将被调用

2.5 批改配置文件

残缺的配置文件内容如下:


<?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:p="http://www.springframework.org/schema/p"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="
            http://www.springframework.org/schema/beans 
            http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">

        <bean id="beanPostProcessor" class="com.tom.lifecycle.GPBeanPostProcessor" />

        <bean id="beanFactoryPostProcessor" class="com.tom.lifecycle.GPBeanFactoryPostProcessor" />

        <bean id="instantiationAwareBeanPostProcessor" class="com.tom.lifecycle.GPInstantiationAwareBeanPostProcessor" />


        <bean id="author" class="com.tom.lifecycle.Author"
                init-method="beanInit"
                destroy-method="beanDestory"
                scope="singleton"
                p:name="Tom" p:address="湖南长沙" p:age="18"/>

</beans>

2.6 运行后果

最初,咱们再次运行 BeanLifeCycleTest 测试类,看到如下运行后果:

15:56:20.030 [main] INFO com.tom.lifecycle.GPBeanFactoryPostProcessor - 调用 BeanFactoryPostProcessor 实现类结构器!!15:56:20.045 [main] INFO com.tom.lifecycle.GPBeanFactoryPostProcessor - BeanFactoryPostProcessor 调用 postProcessBeanFactory 办法
15:56:20.046 [main] INFO com.tom.lifecycle.GPBeanPostProcessor - 调用 BeanPostProcessor 实现类结构器!!15:56:20.047 [main] INFO com.tom.lifecycle.GPInstantiationAwareBeanPostProcessor - 调用 InstantiationAwareBeanPostProcessorAdapter 实现类结构器!!15:56:20.051 [main] INFO com.tom.lifecycle.GPInstantiationAwareBeanPostProcessor - InstantiationAwareBeanPostProcessor 调用 postProcessBeforeInstantiation 办法
15:56:20.052 [main] INFO com.tom.lifecycle.Author -【结构器】调用 Tom 类的结构器实例化
15:56:20.069 [main] INFO com.tom.lifecycle.GPInstantiationAwareBeanPostProcessor - InstantiationAwareBeanPostProcessor 调用 postProcessPropertyValues 办法
15:56:20.092 [main] INFO com.tom.lifecycle.Author -【注入属性】address
15:56:20.092 [main] INFO com.tom.lifecycle.Author -【注入属性】age
15:56:20.092 [main] INFO com.tom.lifecycle.Author -【注入属性】name
15:56:20.092 [main] INFO com.tom.lifecycle.Author -【BeanNameAware 接口】调用 setBeanName 办法
15:56:20.092 [main] INFO com.tom.lifecycle.Author -【BeanFactoryAware 接口】调用 setBeanFactory 办法
15:56:20.093 [main] INFO com.tom.lifecycle.GPBeanPostProcessor - BeanPostProcessor 接口办法 postProcessBeforeInitialization 对属性进行更改
15:56:20.093 [main] INFO com.tom.lifecycle.Author -【InitializingBean 接口】调用 afterPropertiesSet 办法
15:56:20.093 [main] INFO com.tom.lifecycle.Author -【init-method】调用 <bean> 的 init-method 属性指定的初始化办法
15:56:20.093 [main] INFO com.tom.lifecycle.GPBeanPostProcessor - BeanPostProcessor 接口办法 postProcessAfterInitialization 对属性进行更改
15:56:20.093 [main] INFO com.tom.lifecycle.GPInstantiationAwareBeanPostProcessor - InstantiationAwareBeanPostProcessor 调用 postProcessAfterInitialization 办法
15:56:20.097 [main] INFO com.tom.lifecycle.BeanLifeCycleTest - ====== 初始化 Spring 容器胜利 ========
15:56:20.098 [main] INFO com.tom.lifecycle.BeanLifeCycleTest - Author(name=Tom, address= 湖南长沙, age=16, beanFactory=org.springframework.beans.factory.support.DefaultListableBeanFactory@26653222: defining beans [beanPostProcessor,beanFactoryPostProcessor,instantiationAwareBeanPostProcessor,author]; root of factory hierarchy, beanName=author)
15:56:20.098 [main] INFO com.tom.lifecycle.BeanLifeCycleTest - ====== 开始销毁 Spring 容器 ========
15:56:20.099 [Thread-0] INFO com.tom.lifecycle.Author -【DiposibleBean 接口】调用 destroy 办法
15:56:20.100 [Thread-0] INFO com.tom.lifecycle.Author -【destroy-method】调用 <bean> 的 destroy-method 属性指定的初始化办法

3 Spring Bean 生命周期运行时序图

最初咱们来看一下残缺的执行时序图:

退出移动版