封面来源:碧蓝航线 逆转彩虹之塔 活动CG

本文基于 SpringBoot 3.1.x

1. 如何获取

一般来说,获取 ApplicationContext 有两种方式:

  1. 实现 ApplicationContextAware 接口,Spring 会在合适的时机回调 setApplicationContext() 方法,获取到 ApplicationContext 实例;
  2. 使用 @Autowired 注解直接注入 ApplicationContext 实例。

2. 注入 ApplicationContext

2.1 使用示例

1
2
3
4
5
6
7
8
9
10
@Component
static class MyApplicationContext {
    private ApplicationContext applicationContext;

    @Autowired
    public void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
        System.out.println("1. 使用 @Autowired 注入 ApplicationContext");
    }
}

Spring 容器启动过程中,控制台打印出:

1. 使用 @Autowired 注入 ApplicationContext

除了使用 Setter 注入,使用构造方法注入、字段注入也都是可以的。

ApplicationContext 虽然能够通过 @Autowired 注解注入到 Bean 中,但 ApplicationContext 本身并不是 Spring 容器中的一个 Bean,如果想通过 getBean(ApplicationContext.class) 方式获取 ApplicationContext,则会抛出 NoSuchBeanDefinitionException 异常,显示没有可用的 ApplicationContext 类型的 Bean。

2.2 为什么能注入 ApplicationContext

既然 Spring 容器中并不存在 ApplicationContext 类型的 Bean,那为什么又能通过 @Autowired 注解注入呢?

Spring 容器中的普通 Bean 元数据信息都是存放在 DefaultListableBeanFactory 中的,比如:

1
2
3
4
// BeanDefinition 集合,key 为 Bean 的名称
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
// 按注册顺序写入的 BeanDefinition 名称
private volatile List<String> beanDefinitionNames = new ArrayList<>(256);

ApplicationContext 也是存放在 DefaultListableBeanFactory 类中的,只不过放在 resolvableDependencies 中:

1
private final Map<Class<?>, Object> resolvableDependencies = new ConcurrentHashMap<>(16);

resolvableDependencies 中存放的都是一些能够被 @Autowired 注解注入的依赖项,但不包含普通的 Bean。

在查找依赖(比如使用 @Autowired)时,会同时在 beanDefinitionNamesresolvableDependencies 搜索,因此能够注入 ApplicationContext;而 getBean 时,只会在 BeanDefinitionMap 中搜索,ApplicationContext 自然也就找不到了。

2.3 注册 ApplicationContext

ApplicationContext 在准备 BeanFactory 时就被加载了,实现逻辑在著名的 org.springframework.context.support.AbstractApplicationContext#refresh() 中:

1
2
3
4
5
6
7
8
9
10
11
@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // --snip--

        // Prepare the bean factory for use in this context.
        prepareBeanFactory(beanFactory);

        // --snip--
    }
}

而在 prepareBeanFactory() 方法中有:

1
2
3
4
5
6
7
8
9
10
11
12
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // --snip--
    
    // BeanFactory interface not registered as resolvable type in a plain factory.
    // MessageSource registered (and found for autowiring) as a bean.
    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    beanFactory.registerResolvableDependency(ApplicationContext.class, this);
    
    // --snip--
}

beanFactory.registerResolvableDependency() 方法用于设置依赖注入某种类型的对象,比如:

1
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);

当进行如下的依赖注入时:

1
2
@Autowired
private BeanFactory beanFactory;

实际注入的是 beanFactory.registerResolvableDependency() 方法的第二个参数,即 prepareBeanFactory() 方法的 beanFactory 参数。

再比如后面的三行表示注入 ResourceLoaderApplicationEventPublisherApplicationContext 时,注入的对象是 this,即:ApplicationContext

简单来说:通过 @Autowired 注解注入 BeanFactoryResourceLoaderApplicationEventPublisherApplicationContext

2.4 @Autowired 的实现

@Autowired 注解的实现离不开 AutowiredAnnotationBeanPostProcessor,它又是什么时候创建的、什么时候执行的呢?

以 SpringBoot 中最主要的 run() 方法为入口,org.springframework.boot.SpringApplication#run(java.lang.String...) 方法中的执行逻辑分为以下几步:

flowchart TD 
1("reateBootstrapContext()")
2("configureHeadlessProperty")
3("getRunListeners() & listeners.starting()")
4("prepareEnvironment()")
5("printBanner()")
subgraph 6 ["createApplicationContext()"]
6.1("注册 AutowiredAnnotationBeanPostProcessor 的 BeanDefinition"):::orange-red-filling
end
7("prepareContext()")
subgraph 8 ["refreshContext()"]
    direction TB
    8.1("实例化 AutowiredAnnotationBeanPostProcessor"):::orange-red-filling
    8.2("创建 Bean 时进行依赖注入"):::orange-red-filling
end
9("afterRefresh()")
10("listeners.started()")
11("callRunners()")
1 --> 2 --> 3 --> 4 --> 5 --> 6 --> 7 --> 8 --> 9 --> 10 --> 11
8.1 --> 8.2
classDef orange-red-filling fill:#f96;

注册 AutowiredAnnotationBeanPostProcessorBeanDefinition

在执行 createApplicationContext() 方法时,默认创建 AnnotationConfigApplicationContext

1
2
3
4
5
6
public AnnotationConfigApplicationContext() {
    StartupStep createAnnotatedBeanDefReader = this.getApplicationStartup().start("spring.context.annotated-bean-reader.create");
    this.reader = new AnnotatedBeanDefinitionReader(this);
    createAnnotatedBeanDefReader.end();
    this.scanner = new ClassPathBeanDefinitionScanner(this);
}

然后又会创建 AnnotatedBeanDefinitionReader

1
2
3
4
5
6
7
8
9
10
11
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
    this(registry, getOrCreateEnvironment(registry));
}

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    Assert.notNull(environment, "Environment must not be null");
    this.registry = registry;
    this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
    AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}

调用 AnnotationConfigUtils#registerAnnotationConfigProcessors() 方法时,将 AutowiredAnnotationBeanPostProcessorBeanDefinition 注册到容器中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
    registerAnnotationConfigProcessors(registry, null);
}

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
    BeanDefinitionRegistry registry, @Nullable Object source) {
    // --snip--
    if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
    }
    // --snip--
}

从这段代码还能知道 AutowiredAnnotationBeanPostProcessor 对应的 beanName 是 AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME

1
2
public static final String AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME =
    "org.springframework.context.annotation.internalAutowiredAnnotationProcessor";

实例化 AutowiredAnnotationBeanPostProcessor

实例化是在 refreshContext() 方法中完成的,最终会来到 org.springframework.context.support.AbstractApplicationContext#refresh() 方法中:

1
2
3
4
5
6
7
8
9
10
11
12
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // --snip--

        try {
            // --snip--

            // Register bean processors that intercept bean creation.
            registerBeanPostProcessors(beanFactory);
        }
    }
}

真正的实例化工作委托给 PostProcessorRegistrationDelegate#registerBeanPostProcessors() 方法:

1
2
3
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
   PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}

在该方法内部获取到所有的 BeanPostProcessor,然后按照优先级、不同的分类完成实例化。

依赖注入

以常见的单例 Bean 为例,单例 Bean 的初始化同样是在 org.springframework.context.support.AbstractApplicationContext#refresh() 方法中完成:

1
2
3
4
5
6
7
8
9
10
11
12
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // --snip--

        try {
            // --snip--

            // Instantiate all remaining (non-lazy-init) singletons.
            finishBeanFactoryInitialization(beanFactory);
        }
    }
}

finishBeanFactoryInitialization() 方法中又调用了 preInstantiateSingletons() 方法:

1
2
3
4
5
6
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    // --snip--
    
    // Instantiate all remaining (non-lazy-init) singletons.
    beanFactory.preInstantiateSingletons();
}

最终来到 DefaultListableBeanFactory#preInstantiateSingletons() 方法里:

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
public void preInstantiateSingletons() throws BeansException {
    if (logger.isTraceEnabled()) {
        logger.trace("Pre-instantiating singletons in " + this);
    }

    // Iterate over a copy to allow for init methods which in turn register new bean definitions.
    // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
    List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

    // Trigger initialization of all non-lazy singleton beans...
    for (String beanName : beanNames) {
        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
        // 不是抽象的、是单例的、没有延迟加载
        if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
            // 是工厂 Bean 走这
            if (isFactoryBean(beanName)) {
                Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
                if (bean instanceof SmartFactoryBean<?> smartFactoryBean && smartFactoryBean.isEagerInit()) {
                    getBean(beanName);
                }
            }
            else {
                // 否则走这
                getBean(beanName);
            }
        }
    }

    // Trigger post-initialization callback for all applicable beans...
    for (String beanName : beanNames) {
        Object singletonInstance = getSingleton(beanName);
        if (singletonInstance instanceof SmartInitializingSingleton smartSingleton) {
            StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
                .tag("beanName", beanName);
            smartSingleton.afterSingletonsInstantiated();
            smartInitialize.end();
        }
    }
}

最终调用了 getBean() 方法:

1
2
3
public Object getBean(String name) throws BeansException {
   return doGetBean(name, null, null, false);
}

doGetBean() 中创建单例 Bean:

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
protected <T> T doGetBean(
    String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
    throws BeansException {
    // --snip--

    // Create bean instance.
    if (mbd.isSingleton()) {
        sharedInstance = getSingleton(beanName, () -> {
            try {
                // 创建 Bean
                return createBean(beanName, mbd, args);
            }
            catch (BeansException ex) {
                // Explicitly remove instance from singleton cache: It might have been put there
                // eagerly by the creation process, to allow for circular reference resolution.
                // Also remove any beans that received a temporary reference to the bean.
                destroySingleton(beanName);
                throw ex;
            }
        });
        beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
    }

    // --snip--
}

创建 Bean 的 createBean() 方法最终会调用 AbstractAutowireCapableBeanFactory#createBean() 方法,而在该方法中又会调用 doCreateBean() 方法,总之就是套娃:

1
2
3
4
5
6
7
8
9
10
11
12
13
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
    throws BeanCreationException {
    //  --snip--
    try {
        // 继续套娃
        Object beanInstance = doCreateBean(beanName, mbdToUse, args);
        if (logger.isTraceEnabled()) {
            logger.trace("Finished creating instance of bean '" + beanName + "'");
        }
        return beanInstance;
    }
    // --snip--
}

doCreateBean() 方法中完成单例 Bean 的初始化,初始化之前会调用 populateBean() 方法填充 Bean,也就是进行依赖注入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
    throws BeanCreationException {
    // --snip--
    // Initialize the bean instance.
    Object exposedObject = bean;
    try {
        // 填充 Bean:进行依赖注入
        populateBean(beanName, mbd, instanceWrapper);
        // 初始化 Bean
        exposedObject = initializeBean(beanName, exposedObject, mbd);
    }
    catch (Throwable ex) {
        if (ex instanceof BeanCreationException bce && beanName.equals(bce.getBeanName())) {
            throw bce;
        }
        else {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, ex.getMessage(), ex);
        }
    }
    // --snip--
}

populateBean() 方法中会对所有 InstantiationAwareBeanPostProcessor 进行循环,调用它们的 postProcessProperties() 方法,而 AutowiredAnnotationBeanPostProcessor 就是它们中的一员:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    // --snip--
    if (hasInstantiationAwareBeanPostProcessors()) {
        if (pvs == null) {
            pvs = mbd.getPropertyValues();
        }
        for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
            PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
            if (pvsToUse == null) {
                return;
            }
            pvs = pvsToUse;
        }
    }
    // --snip--
}

AutowiredAnnotationBeanPostProcessorpostProcessProperties() 方法中,先获取到 InjectionMetadata(注入元数据),然后执行 inject() 方法完成注入:

1
2
3
4
5
6
7
8
9
10
11
12
13
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
   InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
   try {
      metadata.inject(bean, beanName, pvs);
   }
   catch (BeanCreationException ex) {
      throw ex;
   }
   catch (Throwable ex) {
      throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
   }
   return pvs;
}

findAutowiringMetadata() 方法中会调用 buildAutowiringMetadata() 方法:

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
private InjectionMetadata buildAutowiringMetadata(Class<?> clazz) {
    // --snip--

    do {
        final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();

        ReflectionUtils.doWithLocalFields(targetClass, field -> {
            // 查看字段上是否有依赖注入相关的注解
            MergedAnnotation<?> ann = findAutowiredAnnotation(field);
            if (ann != null) {
                if (Modifier.isStatic(field.getModifiers())) {
                    if (logger.isInfoEnabled()) {
                        logger.info("Autowired annotation is not supported on static fields: " + field);
                    }
                    return;
                }
                boolean required = determineRequiredStatus(ann);
                // 添加 InjectedElement
                currElements.add(new AutowiredFieldElement(field, required));
            }
        });
        
        // 反射遍历方法
    }
    while (targetClass != null && targetClass != Object.class);

    return InjectionMetadata.forElements(elements, clazz);
}

buildAutowiringMetadata() 方法内部使用反射遍历 Bean 中的每个字段和方法,查看它们是否有依赖注入相关的注解,这个逻辑由 findAutowiredAnnotation() 方法完成:

1
2
3
4
5
6
7
8
9
10
private MergedAnnotation<?> findAutowiredAnnotation(AccessibleObject ao) {
    MergedAnnotations annotations = MergedAnnotations.from(ao);
    for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
        MergedAnnotation<?> annotation = annotations.get(type);
        if (annotation.isPresent()) {
            return annotation;
        }
    }
    return null;
}

this.autowiredAnnotationTypes 中的数据是构造 AutowiredAnnotationBeanPostProcessor 添加的,可以看到支持 @Autowired@Value@Inject 三种注解:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public AutowiredAnnotationBeanPostProcessor() {
    this.autowiredAnnotationTypes.add(Autowired.class);
    this.autowiredAnnotationTypes.add(Value.class);

    try {
        this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
                                          ClassUtils.forName("jakarta.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
        logger.trace("'jakarta.inject.Inject' annotation found and supported for autowiring");
    }
    catch (ClassNotFoundException ex) {
        // jakarta.inject API not available - simply skip.
    }

    try {
        this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
                                          ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
        logger.trace("'javax.inject.Inject' annotation found and supported for autowiring");
    }
    catch (ClassNotFoundException ex) {
        // javax.inject API not available - simply skip.
    }
}

那注入的数据又是怎么来的呢?

回到 AutowiredAnnotationBeanPostProcessor#buildAutowiringMetadata() 方法中,如果字段上有依赖注入相关的注解,并且字段没有被 static 修饰,那么就会创建一个 AutowiredFieldElement 对象,最终使用 InjectionMetadata.forElements() 方法将所有的 AutowiredFieldElement 对象整合到 InjectionMetadata 对象中。

所有的 AutowiredFieldElement 对象被整合到 InjectionMetadatainjectedElements 字段中。

完成 InjectionMetadata 对象的组装后,回到 AutowiredAnnotationBeanPostProcessor#postProcessProperties() 方法中,接下来执行 inject() 方法完成依赖注入:

1
2
3
4
5
6
7
8
9
10
11
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    Collection<InjectedElement> checkedElements = this.checkedElements;
    Collection<InjectedElement> elementsToIterate =
        (checkedElements != null ? checkedElements : this.injectedElements);
    if (!elementsToIterate.isEmpty()) {
        // 遍历 injectedElements,依次执行 inject 方法
        for (InjectedElement element : elementsToIterate) {
            element.inject(target, beanName, pvs);
        }
    }
}

由于 injectedElements 中的元素包括 AutowiredFieldElement 类型,也就是会执行到 AutowiredFieldElementinject() 方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    Field field = (Field) this.member;
    Object value;
    // 有缓存的情况
    if (this.cached) {
        try {
            value = resolvedCachedArgument(beanName, this.cachedFieldValue);
        }
        catch (NoSuchBeanDefinitionException ex) {
            // Unexpected removal of target bean for cached argument -> re-resolve
            value = resolveFieldValue(field, bean, beanName);
        }
    }
    // 无缓存的情况
    else {
        value = resolveFieldValue(field, bean, beanName);
    }
    if (value != null) {
        ReflectionUtils.makeAccessible(field);
        field.set(bean, value);
    }
}

假设并不存在缓存,那么执行 resolveFieldValue() 方法,在该方法中调用 BeanFactoryresolveDependency() 方法来获取依赖注入的值:

1
2
3
4
5
6
7
8
private Object resolveFieldValue(Field field, Object bean, @Nullable String beanName) {
    // --snip--
    Object value;
    try {
        value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
    }
    // --snip--
}

接下来会进入 BeanFactory 的实现类 DefaultListableBeanFactory 中的 resolveDependency() 方法:

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
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
                                @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

    descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
    // 是 Optional 类型
    if (Optional.class == descriptor.getDependencyType()) {
        return createOptionalDependency(descriptor, requestingBeanName);
    }
    // 是 ObjectFactory、ObjectProvider 类型
    else if (ObjectFactory.class == descriptor.getDependencyType() ||
             ObjectProvider.class == descriptor.getDependencyType()) {
        return new DependencyObjectProvider(descriptor, requestingBeanName);
    }
    // 是 Provider 类型
    else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
        return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
    }
    // 否则
    else {
        Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
            descriptor, requestingBeanName);
        if (result == null) {
            result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
        }
        return result;
    }
}

显然会进入最后一个分支,执行 doResolveDependency() 获取依赖注入的值,此方法内部会调用 findAutowireCandidates() 方法,获取依赖注入的候选值,根据候选值信息来到最终应该被依赖注入的值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
protected Map<String, Object> findAutowireCandidates(
    @Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {

    String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
        this, requiredType, true, descriptor.isEager());
    Map<String, Object> result = CollectionUtils.newLinkedHashMap(candidateNames.length);
    // 从 resolvableDependencies 中获取
    for (Map.Entry<Class<?>, Object> classObjectEntry : this.resolvableDependencies.entrySet()) {
        // --snip--
    }
    // 从 BeanDefinitionNames 中寻找
    for (String candidate : candidateNames) {
        if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
            addCandidateEntry(result, candidate, descriptor, requiredType);
        }
    }
    // --snip--
}

至此证明 @Autowired 注解进行依赖注入时可以在 beanDefinitionNamesresolvableDependencies 搜索要被注入的值。

3. ApplicationContextAware 接口

3.1 接口介绍

ApplicationContextAware 接口是 Aware 接口的子接口,Aware 接口是一个标记接口,类似于 Serializable 接口。实现了 Aware 接口的 Bean 能够通过一个回调方法被 Spring 容器通知(这个“通知”通常用来设置一些 Spring 相关的信息,因此回调方法通常以 set 开头,具体内容由各子接口确定),比如 EnvironmentAwareApplicationEventPublisherAware 等接口,以及这里的 ApplicationContextAware 接口。

1
2
3
public interface ApplicationContextAware extends Aware {
    void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}

3.2 使用示例

1
2
3
4
5
6
7
8
9
10
@Component
static class MyApplicationContextAware implements ApplicationContextAware {
    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
        System.out.println("2. Spring 上下文 ApplicationContext 被注入");
    }
}

Spring 容器启动过程中,控制台打印出:

2. Spring 上下文 ApplicationContext 被注入

3.3 源码分析

ApplicationContextAware 的执行与 ApplicationContextAwareProcessor 相关,ApplicationContextAwareProcessor 实现了 BeanPostProcessor 接口,该接口作为 Spring 的拓展点之一,能够在所有 Bean 初始化前和初始化后执行一些处理逻辑。

ApplicationContextAwareProcessor 只重写了 BeanPostProcessor 接口中的 postProcessBeforeInitialization() 方法,使得能够在所有 Bean 初始化前执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
@Override
@Nullable
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
   if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
         bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
         bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware ||
         bean instanceof ApplicationStartupAware)) {
      return bean;
   }

   invokeAwareInterfaces(bean);
   return bean;
}

在重写的方法内部,首先判断当前 Bean 是否实现了一些 Aware 接口,如果没有实现,直接返回,反之执行 invokeAwareInterfaces() 方法。

1
2
3
4
5
6
7
8
private void invokeAwareInterfaces(Object bean) {
   if (bean instanceof Aware) {
      // --snip--
      if (bean instanceof ApplicationContextAware applicationContextAware) {
         applicationContextAware.setApplicationContext(this.applicationContext);
      }
   }
}

invokeAwareInterfaces() 方法中根据不同的接口执行其中不同的方法。

ApplicationContextAwareProcessor 的加载时机

ApplicationContextAwareProcessor 在准备 BeanFactory 时就被加载了,实现逻辑同样是在 org.springframework.context.support.AbstractApplicationContext#refresh() 方法中:

1
2
3
4
5
6
7
8
9
10
11
@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // --snip--

        // Prepare the bean factory for use in this context.
        prepareBeanFactory(beanFactory);

        // --snip--
    }
}

而在 prepareBeanFactory() 方法中有:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // --snip--

    // 加载 ApplicationContextAwareProcessor
    // Configure the bean factory with context callbacks.
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    // 忽略某些类型 Bean 的依赖注入
    beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
    beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
    beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
    beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationStartupAware.class);

    // --snip--
}

beanFactory.ignoreDependencyInterface() 方法用于指定自动装配(autowiring)时忽略的接口,注意 autowiring@Autowired 注解的区别。

ignoreDependencyInterface() 的设置与下面两种场景有关:

  • 基于 XML 进行配置时,<beans> 标签使用 default-autowire="byType" 属性;
  • 基于注解进行配置时,@Bean 注解使用 autowire = Autowire.BY_TYPE 属性,但这个属性在 Spring 5.1 中已被废弃。

当配置了通过类型(BY_TYPE)进行自动装配,在构造某个 Bean 时,如果这个 Bean 中的成员变量对应的类型在 Spring 容器中已存在,并且提供了对应的 Setter,那么此时会自动将对应的 Bean 注入到目标 Bean 中。

对这些 Aware 调用 ignoreDependencyInterface() 方法后,它们将不会被自动装配。

如今采用的都是注解配置,@Bean 注解中的 autowire 属性也被废弃,ignoreDependencyInterface() 方法的使用仅供了解,但不排除它正在某些不起眼的地方发挥着重要的作用呢?

拓展阅读:打开BeanFactory ignoreDependencyInterface方法的正确姿势

4. 两种方式的区别

4.1 触发时机不同

AbstractAutowireCapableBeanFactory#doCreateBean() 方法中,先执行 populateBean() 完成依赖注入,然后执行 initializeBean() 方法初始化 Bean:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
    throws BeanCreationException {
    // --snip--
    // Initialize the bean instance.
    Object exposedObject = bean;
    try {
        // 填充 Bean:进行依赖注入
        populateBean(beanName, mbd, instanceWrapper);
        // 初始化 Bean
        exposedObject = initializeBean(beanName, exposedObject, mbd);
    }
    catch (Throwable ex) {
        if (ex instanceof BeanCreationException bce && beanName.equals(bce.getBeanName())) {
            throw bce;
        }
        else {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, ex.getMessage(), ex);
        }
    }
    // --snip--
}

@Autowired 注解生效在 populateBean() 方法中完成,那 initializeBean() 方法呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
    invokeAwareMethods(beanName, bean);

    Object wrappedBean = bean;
    // 调用 BeanPostProcessor 的 postProcessBeforeInitialization() 方法
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }

    try {
        // 执行初始化方法
        invokeInitMethods(beanName, wrappedBean, mbd);
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
            (mbd != null ? mbd.getResourceDescription() : null), beanName, ex.getMessage(), ex);
    }
    // 调用 BeanPostProcessor 的 postProcessAfterInitialization() 方法 
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }

    return wrappedBean;
}

ApplicationContextAware 接口中的 setApplicationContext() 方法的执行与 ApplicationContextAwareProcessor 相关,在其重写的 postProcessBeforeInitialization() 方法中执行。

因此,@Autowired 注解获取 ApplicationContext 的方式要早于重写 ApplicationContextAware 接口的方式。

使用 @Autowired 注解获取 ApplicationContext 并不是完全等价重写 ApplicationContextAware 接口来获取,在某些情况下,使用 @Autowired 注解无法获取到 ApplicationContext,而是只能通过重写 ApplicationContextAware 接口完成,具体内容参考 SpringBoot 常用拓展点 一文中对 ApplicationContextAware 的补充。

4.2 自定义程度不同

使用 @Autowired 注解就只能注入“干巴巴”的 ApplicationContext,而实现 ApplicationContextAware 接口可以进行更多的自定义逻辑。