整体流程

要想搞清楚Spring核心代码的运作流程,其实也比较好办,那就是调试一下Spring Context的初始化过程,这个过程搞清楚了,整个Spring的核心体系也就搞清楚了。

要弄清楚这个流程,可以创建一个最最基本的spirng应用,只保留spring最核心的spring-context和spring-beans的依赖,然后进行调试,这样就能够清晰地看到spring体系加载的主线流程。

下面是一个十分精简的spring应用,应用中只有一个Bean,一个自定义的BeanPostProcess,以及一个主程序。

image-20210810121312988

  • Person.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
package net.liwenbo.myspring;

public class Person {

    private String name;

    private int age;

    private int gender;

    public Person(String name, int age, int gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }

    public void eat() {
        System.out.println(name + " eating...");
    }
}
  • SpringTest.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
// SpringTest.java
package net.liwenbo.myspring;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;

public class SpringTest {

    public static void main(String[] args) {

        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringTest.class);

        Person lwb = context.getBean("person", Person.class);
        lwb.eat();
    }

    @Bean
    public Person person() {
        return new Person("liwenbo", 36, 1);
    }
}
  • MyBeanPostProcessor.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
package net.liwenbo.myspring;

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

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("Invoke postProcessBeforeInitialization, bean Name = " + beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("Invoke postProcessAfterInitialization, bean Name = " + beanName);
        return bean;
    }
}

pom.xml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>net.liwenbo</groupId>
    <artifactId>myspring</artifactId>
    <version>1.0.0-SNAPSHOT</version>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.16.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.2.16.RELEASE</version>
        </dependency>
    </dependencies>
</project>

运行这个程序,可以在 postProcessBeforeInitialization 处打一个断点,这样就能很方便地看到整个初始化过程的调用堆栈了。

image-20210810121810832

下图为初始化非懒加载的单例beans的时候的调用堆栈。

image-20210810122017908

AbstractApplicationContext中的 refresh 方法,是整个容器初始化过程中的关键入口。这里很明显采用了模板方法模式,很多处理需要子类来自己实现。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
	@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// 准备容器刷新
			prepareRefresh();

      // 告诉子类去刷新内部的bean工厂
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

      // 准备本context的beanFactory
			prepareBeanFactory(beanFactory);

			try {
        // 允许子类中进行beanFacotry的后续处理
				postProcessBeanFactory(beanFactory);

        // 调用本context注册的beanFacotry的后置处理器
				invokeBeanFactoryPostProcessors(beanFactory);

        // 注册Bean的后置处理器(BeanPostProcessor)
				registerBeanPostProcessors(beanFactory);

				// 初始化消息源
				initMessageSource();

        // 初始化应用的事件多播机制
				initApplicationEventMulticaster();

        // 这个是需要子类去实现的,一些在初始化过程中的特定操作
				onRefresh();

        // 检查并注册监听器
				registerListeners();

				// 初始化所有非懒加载的bean,我们的bean就是在这里创建的
        // 可以看到上图里面的调用链,doCreateBean是真正创建Bean的方法
        // 创建和初始化Bean的过程中,就会调用BeanPostProcessor中的方法
				finishBeanFactoryInitialization(beanFactory);

        // 完成刷新,调用LifecycleProcessor的onRefresh方法,发出ContextRefreshedEvent事件
				finishRefresh();
			}
			catch (BeansException ex) {
				// 有异常,处理,清理容器,代码略
                ...
			}
			finally {
        // 清理Spring core里面的一些缓存,因为对于一些单例的bean,我们可能再也不需要他们的metadata了
				resetCommonCaches();
			}
		}
	}

Bean的创建

Bean的创建的前三个阶段:实例化、属性赋值、初始化,主要逻辑都在doCreateBean()方法中,逻辑比较清晰,就是顺序调用以下三个方法,这三个方法与三个生命周期阶段一一对应,非常重要,在后续扩展接口分析中也会涉及。

  • createBeanInstance() -> 实例化

  • populateBean() -> 属性赋值

  • initializeBean() -> 初始化

源码如下,能证明实例化,属性赋值和初始化这三个生命周期的存在。关于本文的Spring源码都将忽略无关部分,便于理解:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// Bean创建的大致过程,忽略非核心代码
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {
    
    // 实例化Bean
    BeanWrapper instanceWrapper = null;
    if (instanceWrapper == null) {
		instanceWrapper = createBeanInstance(beanName, mbd, args);
	}
    
  // 初始化Bean实例
	Object exposedObject = bean;
	try {
    // 属性赋值
		populateBean(beanName, mbd, instanceWrapper);
        
    // 初始化Bean
		exposedObject = initializeBean(beanName, exposedObject, mbd);
	}
    
    // 其他的一些处理
    ....
        
    return exposedObject;
}    

销毁Bean阶段:

至于销毁,是在容器关闭时调用的,详见 ConfigurableApplicationContext#close()

生命周期常用扩展点

Spring生命周期相关的常用扩展点非常多,所以问题不是不知道,而是记不住或者记不牢。其实记不住的根本原因还是不够了解,这里通过源码+分类的方式帮大家记忆。

区分影响一个bean或者多个bean是从源码分析得出的。

以BeanPostProcessor为例:

  1. 从refresh方法来看,BeanPostProcessor 实例化比正常的bean早。

  2. 从initializeBean方法看,每个bean初始化前后都调用所有BeanPostProcessor的postProcessBeforeInitialization和postProcessAfterInitialization方法。

第一大类:影响多个Bean的接口

实现了这些接口的Bean会切入到多个Bean的生命周期中。正因为如此,这些接口的功能非常强大,Spring内部扩展也经常使用这些接口,例如自动注入以及AOP的实现都和他们有关。

  • InstantiationAwareBeanPostProcessor

  • BeanPostProcessor

这两兄弟可能是Spring扩展中最重要的两个接口,InstantiationAwareBeanPostProcessor作用于实例化阶段的前后BeanPostProcessor 作用于初始化阶段的前后。正好和第一、第三个生命周期阶段对应。通过图能更好理解:

未命名文件(2)

InstantiationAwareBeanPostProcessor

InstantiationAwareBeanPostProcessor实际上继承了BeanPostProcessor接口,严格意义上来看他们不是两兄弟,而是两父子。但是从生命周期角度我们重点关注其特有的对实例化阶段的影响,图中省略了从BeanPostProcessor继承的方法。

在MyInstitationProcessor的postProcessBeforeInstantiation方法上打上断点,通过调试,可以清晰地看到该方法的调用路径。

image-20210810134236057

可以看到,postProcessBeforeInstantiation在doCreateBean之前调用,也就是在bean实例化之前调用的,英文源码注释解释道该方法的返回值会替换原本的Bean作为代理,这也是Aop等功能实现的关键点。

image-20210810134401638

可以看到该方法在属性赋值方法内,但是在真正执行赋值操作之前。其返回值为boolean,返回false时可以阻断属性赋值阶段(continueWithPropertyPopulation = false;)。

BeanPostProcessor

关于BeanPostProcessor执行阶段的源码穿插在下文Aware接口的调用时机分析中,因为部分Aware功能的就是通过他实现的!只需要先记住BeanPostProcessor在初始化前后调用就可以了。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
	protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
		// ...
		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		
        //...

		return wrappedBean;
	}

这一大类接口的特点是功能丰富,常用于用户自定义扩展。

第二大类中又可以分为两类:

Aware类型的接口

生命周期接口,无所不知的Aware。Aware类型的接口的作用就是让我们能够拿到Spring容器中的一些资源。基本都能够见名知意,Aware之前的名字就是可以拿到什么资源,例如BeanNameAware可以拿到BeanName,以此类推。调用时机需要注意:所有的Aware方法都是在初始化阶段之前调用的!

Aware接口众多,这里同样通过分类的方式帮助大家记忆。Aware接口具体可以分为两组,至于为什么这么分,详见下面的源码分析。如下排列顺序同样也是Aware接口的执行顺序,能够见名知意的接口不再解释。

Aware Group1

  • BeanNameAware
  • BeanClassLoaderAware
  • BeanFactoryAware

Aware Group2

  • EnvironmentAware
  • EmbeddedValueResolverAware: 这个知道的人可能不多,实现该接口能够获取Spring EL解析器,用户的自定义注解需要支持spel表达式的时候可以使用,非常方便。
  • ApplicationContextAware: ( ResourceLoaderAware \ ApplicationEvent PublisherAware \ MessageSourceAware) 这几个接口可能让人有点懵,实际上这几个接口可以一起记,其返回值实质上都是当前的ApplicationContext对象,因为ApplicationContext是一个复合接口。

Aware调用时机源码分析

详情如下,忽略了部分无关代码。代码位置就是我们上文提到的initializeBean方法详情,这也说明了Aware都是在初始化阶段之前调用的!

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// Aware相关的接口都是在initializeBean方法中调用,但调用时机不太相同
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
	
    // 这段代码invokeAwareMethods调用Group1中BeanXXXAware
   	if (System.getSecurityManager() != null) {
		AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
			invokeAwareMethods(beanName, bean);
			return null;
		}, getAccessControlContext());
	} else {
		invokeAwareMethods(beanName, bean);
	}

    // 这里调用Group2中的几个Aware,调用postProcessBeforeInitialization
    Object wrappedBean = bean;
	if (mbd == null || !mbd.isSynthetic()) {
		wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
	}

    // 调用初始化方法
    try {
		invokeInitMethods(beanName, wrappedBean, mbd);
	} catch (Throwable ex) {
		// ...
	}
    
    // 调用postProcessAfterInitialization
	if (mbd == null || !mbd.isSynthetic()) {
		wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
	}

	return wrappedBean;
}

可以看到并不是所有的Aware接口都使用同样的方式调用。Bean××Aware都是在代码中直接调用的,而ApplicationContext相关的Aware都是通过BeanPostProcessor#postProcessBeforeInitialization()实现的。感兴趣的可以自己看一下ApplicationContextAwareProcessor这个类的源码,就是判断当前创建的Bean是否实现了相关的Aware方法,如果实现了会调用回调方法将资源传递给Bean。

至于Spring为什么这么实现,应该没什么特殊的考量。也许和Spring的版本升级有关。基于对修改关闭,对扩展开放的原则,Spring对一些新的Aware采用了扩展的方式添加。

BeanPostProcessor的调用时机也能在这里体现,包围住invokeInitMethods方法,也就说明了在初始化阶段的前后执行。关于Aware接口的执行顺序,其实只需要记住第一组在第二组执行之前就行了。每组中各个Aware方法的调用顺序其实没有必要记,有需要的时候点进源码一看便知。

生命周期接口

至于剩下的两个生命周期接口就很简单了,实例化和属性赋值都是Spring帮助我们做的,能够自己实现的有初始化和销毁两个生命周期阶段。

InitializingBean接口

InitializingBean顾名思义,是初始化Bean相关的接口。接口定义:

1
2
3
public interface InitializingBean {
  void afterPropertiesSet() throws Exception;
}

看方法名,是在读完Properties文件,之后执行的方法。afterPropertiesSet()方法是在初始化过程中被调用的。InitializingBean 对应生命周期的初始化阶段,在上面源码的invokeInitMethods(beanName, wrappedBean, mbd); 方法中调用。

有一点需要注意,因为Aware方法都是执行在初始化方法之前,所以可以在初始化方法中放心大胆的使用Aware接口获取的资源,这也是我们自定义扩展Spring的常用方式。

除了实现InitializingBean接口之外还能通过注解(@PostConstruct)或者xml配置的方式指定初始化方法(init-method),至于这几种定义方式的调用顺序其实没有必要记。因为这几个方法对应的都是同一个生命周期,只是实现方式不同,我们一般只采用其中一种方式。

三种实现指定初始化方法的方法

  1. 使用@PostConstruct注解,该注解作用于void方法上
1
2
3
4
5
6
7
8
public class Person {	    
  ...       
  @PostConstruct
  public void addTitle() {        
    this.title = "Mr. ";    
  }        
  ...
}
  1. 在配置文件中配置init-method方法
1
2
3
<bean id="person" class="net.liwenbo.myspring.Person" init-method="addTitle">
  ...
</bean>
  1. 将类实现InitializingBean接口
1
2
3
4
5
6
7
8
public class Person implements InitializingBean {	    
  ...

  @Override
  public void afterPropertiesSet() throws Exception {
    this.title = "Mr. ";
  }
}

DisposableBean接口

DisposableBean类似于InitializingBean,对应生命周期的销毁阶段,以ConfigurableApplicationContext#close()方法作为入口,实现是通过循环获取所有实现了DisposableBean接口的Bean然后调用其destroy()方法 。

接口定义:

1
2
3
4
5
6
7
8
public interface DisposableBean {
  /**	 
  * Invoked by the containing {@code BeanFactory} on destruction of a bean.	
  * @throws Exception in case of shutdown errors. Exceptions will get logged	 
  * but not rethrown to allow other beans to release their resources as well.	 
  */	
  void destroy() throws Exception;
}

定义一个实现了DisposableBean接口的Bean:

1
2
3
4
5
6
7
public class Person implements DisposableBean {    
  ...    
  @Override    
  public void destroy() throws Exception {
    System.out.println("destroy my bean!");
  }
}

也就是说,在对象销毁的时候,会去调用DisposableBean的destroy方法。在进入到销毁过程时先去调用一下DisposableBean的destroy方法,然后后执行 destroy-method声明的方法(用来销毁Bean中的各项数据)。

BeanPostProcessor注册时机与执行顺序

首先要明确一个概念,在spring中一切皆bean。所有的组件都会被作为一个bean装配到spring容器中,过程如下图:

image-20210810153119327

所以我们前面所讲的那些拓展点,也都会被作为一个个bean装配到spring容器中。

注册时机: 我们知道BeanPostProcessor也会注册为Bean,那么Spring是如何保证BeanPostProcessor 在我们的业务Bean之前初始化完成呢?

请看我们熟悉的refresh()方法的源码,可以看出,Spring是先执行registerBeanPostProcessors()进行BeanPostProcessors的注册,然后再执行finishBeanFactoryInitialization创建我们的单例非懒加载的Bean。

执行顺序:

BeanPostProcessor有很多个,而且每个BeanPostProcessor都影响多个Bean,其执行顺序至关重要,必须能够控制其执行顺序才行。关于执行顺序这里需要引入两个排序相关的接口:PriorityOrdered、Ordered

  • PriorityOrdered是一等公民,首先被执行,PriorityOrdered公民之间通过接口返回值排序
  • Ordered是二等公民,然后执行,Ordered公民之间通过接口返回值排序
  • 都没有实现是三等公民,最后执行

在以下源码中,可以很清晰的看到Spring注册各种类型BeanPostProcessor的逻辑,根据实现不同排序接口进行分组。优先级高的先加入,优先级低的后加入。根据排序接口返回值排序,默认升序排序,返回值越低优先级越高。

FactoryBean 和 BeanFactory 区别

BeanFactory 是 Bean 的工厂, ApplicationContext 的父类,IOC 容器的核心,负责生产和管理 Bean 对象。

FactoryBean 是 Bean,可以通过实现 FactoryBean 接口定制实例化 Bean 的逻辑,通过代理一个Bean对象,对方法前后做一些操作。

  • BeanFactory 是ioc容器的底层实现接口,是ApplicationContext 顶级接口。

Spring不允许我们直接操作 BeanFactory bean工厂,所以为我们提供了ApplicationContext 这个接口 此接口集成BeanFactory 接口,ApplicationContext包含BeanFactory的所有功能,同时还进行更多的扩展。

BeanFactory 接口又衍生出以下接口,其中我们经常用到的是ApplicationContext 接口。

  • FactoryBean 是spirng提供的工厂bean的一个接口**。**

FactoryBean 接口提供三个方法,用来创建对象,FactoryBean 具体返回的对象是由getObject 方法决定的。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
public interface FactoryBean<T> {	
  // 创建具体的Bean对象类型
  @Nullable	T getObject() throws Exception;
  
  // 返回这个工厂Bean创建的对象的类型
  @Nullable	Class<?> getObjectType();
  
  // 是否是单例,默认true	
  default boolean isSingleton() {
    return true;
  }
}

例如,下面的代码创建了一个FactoryBean 用来生产Person对象。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
public class PersonFactoryBean implements FactoryBean<Person> {
  @Override
  public Person getObject() throws Exception {
    return new Person();
  }
  
  @Override
  public Class<?> getObjectType() {
    return Person.class;
  }
}

总之,BeanFactory是个bean 工厂,是一个工厂类(接口), 它负责生产和管理bean的一个工厂,是ioc 容器最底层的接口,是个ioc容器,是spring用来管理和装配普通bean的ioc容器(这些bean成为普通bean)。

FactoryBean是个bean,在IOC容器的基础上给Bean的实现加上了一个简单工厂模式和装饰模式,是一个可以生产对象和装饰对象的工厂bean,由spring管理后,生产的对象是由getObject()方法决定的(从容器中获取到的对象不是“ FactoryBeanTest ” 对象)。

Spring 如何解决循环依赖

Spring是如何处理循环依赖的,比如几个Bean之间的互相引用,例如下面的代码,PersonA依赖于PersonB,PersonB依赖于PersonC,PersonC依赖于PersonA。

  • PersonA.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
@Component
public class PersonA {
  @Autowired
  private PersonB personB;
  
  private String name;
  
  public PersonA() {
    name = "personA";
  }
}
  • PersonB.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
@Component
public class PersonB {
  @Autowired
  private PersonC personC;
  
  private String name;
  
  public PersonB() {
    name = "PersonB";
  }
}
  • PersonC.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
@Component
public class PersonC {
  @Autowired
  private PersonC personC;
  
  private String name;
  
  public PersonC() {
    name = "PersonC";
  }
}

如果三个类都不是单例的方式 ,那么Spring肯定会报循环依赖的异常。对于循环依赖链上有单例的情况,Spring主要是采用三级缓存的方式来解决循环依赖。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// DefaultSingletonBeanRegistry.java
// Spring解决循环依赖的关键在于这个类
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
  /** Cache of singleton objects: bean name to bean instance. */
  private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
  
  /** Cache of singleton factories: bean name to ObjectFactory. */
  private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
  
  /** Cache of early singleton objects: bean name to bean instance. */
  private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
  
  /** Set of registered singletons, containing the bean names in registration order. */
  private final Set<String> registeredSingletons = new LinkedHashSet<>(256);
  
  /**
  * Add the given singleton factory for building the specified singleton	 
  * if necessary.	 
  * <p>To be called for eager registration of singletons, e.g. to be able to	
  * resolve circular references.
  * @param beanName the name of the bean	
  * @param singletonFactory the factory for the singleton object	 */	
  protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
    Assert.notNull(singletonFactory, "Singleton factory must not be null");
    synchronized (this.singletonObjects) {
      if (!this.singletonObjects.containsKey(beanName)) {
        this.singletonFactories.put(beanName, singletonFactory);
        this.earlySingletonObjects.remove(beanName);
        this.registeredSingletons.add(beanName);
      }
    }
  }
}

具体的解决循环依赖的细节,可以通过调试Bean创建的过程梳理清楚。Spring 解决循环依赖的方法可以总结为下面几点:

1. 首先, Spring 提供 setAllowCircularReferences 方法可以设置是否开启循环依赖,默认是允许循环依赖。

2. 其次, Spring 设计了三个集合来处理循环依赖,分别是 singletonFactories,earlySingletonObjects,registeredSingletons

  • singletonFactories 用来缓存 Bean 创建的 Lamdba 表达式创建方法;

  • earlySingletonObjects 用来缓存早期的 bean 的引用;

  • registeredSingletons 记录已经注册的 bean。

3. 最后, 当一个类 A 通过字段注入的方式依赖另一个类 B 的时候,如果 IoC 容器也没有 B 类的缓存,核心方法 DefaultSingletonBeanRegistry#getSingleton(java.lang.String, boolean)

  • 先从 singletonFactories 获取到当前 bean 的实例创建方法;
  • 再通过 getObject 方法获取到早期的 bean 的实例引用;
  • 最后将这个 bean 的实例设置当前的字段属性中。

Sring核心源码总结

Spring Bean的生命周期分为四个阶段多个扩展点。扩展点又可以分为 影响多个Bean影响单个Bean。整理如下:

四个阶段

  • 实例化 Instantiation
  • 属性赋值 Populate
  • 初始化 Initialization
  • 销毁 Destruction

多个扩展点

影响多个Bean

  • BeanPostProcessor
  • InstantiationAwareBeanPostProcessor

影响单个Bean

  • Aware

    • Aware Group1
      • BeanNameAware
      • BeanClassLoaderAware
      • BeanFactoryAware
    • Aware Group2
      • EnvironmentAware
      • EmbeddedValueResolverAware
      • ApplicationContextAware( ResourceLoaderAware \ ApplicationEventPublisherAware \ MessageSourceAware)
  • 生命周期

    • InitializingBean
    • DisposableBean