封面来源:碧蓝航线 逆转彩虹之塔 活动 CG
本文基于 SpringBoot 3.1.x
1. 如何获取
一般来说,获取 ApplicationContext 有两种方式:
- 实现
ApplicationContextAware接口,Spring 会在合适的时机回调setApplicationContext()方法,获取到ApplicationContext实例; - 使用
@Autowired注解直接注入ApplicationContext实例。
2. 注入 ApplicationContext
2.1 使用示例
@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 中的,比如:
// BeanDefinition 集合,key 为 Bean 的名称
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
// 按注册顺序写入的 BeanDefinition 名称
private volatile List<String> beanDefinitionNames = new ArrayList<>(256);
ApplicationContext 也是存放在 DefaultListableBeanFactory 类中的,只不过放在 resolvableDependencies 中:
private final Map<Class<?>, Object> resolvableDependencies = new ConcurrentHashMap<>(16);
resolvableDependencies 中存放的都是一些能够被 @Autowired 注解注入的依赖项,但不包含普通的 Bean。
在查找依赖(比如使用 @Autowired)时,会同时在 beanDefinitionNames 和 resolvableDependencies 搜索,因此能够注入 ApplicationContext;而 getBean 时,只会在 BeanDefinitionMap 中搜索,ApplicationContext 自然也就找不到了。
2.3 注册 ApplicationContext
ApplicationContext 在准备 BeanFactory 时就被加载了,实现逻辑在著名的 org.springframework.context.support.AbstractApplicationContext#refresh() 中:
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// --snip--
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
// --snip--
}
}
而在 prepareBeanFactory() 方法中有:
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() 方法用于设置依赖注入某种类型的对象,比如:
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
当进行如下的依赖注入时:
@Autowired
private BeanFactory beanFactory;
实际注入的是 beanFactory.registerResolvableDependency() 方法的第二个参数,即 prepareBeanFactory() 方法的 beanFactory 参数。
再比如后面的三行表示注入 ResourceLoader、ApplicationEventPublisher 和 ApplicationContext 时,注入的对象是 this,即:ApplicationContext。
简单来说:通过 @Autowired 注解注入 BeanFactory、ResourceLoader、ApplicationEventPublisher 和 ApplicationContext。
2.4 @Autowired 的实现
@Autowired 注解的实现离不开 AutowiredAnnotationBeanPostProcessor,它又是什么时候创建的、什么时候执行的呢?
以 SpringBoot 中最主要的 run() 方法为入口,org.springframework.boot.SpringApplication#run(java.lang.String...) 方法中的执行逻辑分为以下几步:
注册
AutowiredAnnotationBeanPostProcessor的BeanDefinition
在执行 createApplicationContext() 方法时,默认创建 AnnotationConfigApplicationContext:
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:
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() 方法时,将 AutowiredAnnotationBeanPostProcessor 的 BeanDefinition 注册到容器中:
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:
public static final String AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME =
"org.springframework.context.annotation.internalAutowiredAnnotationProcessor";
实例化
AutowiredAnnotationBeanPostProcessor
实例化是在 refreshContext() 方法中完成的,最终会来到 org.springframework.context.support.AbstractApplicationContext#refresh() 方法中:
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// --snip--
try {
// --snip--
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
}
}
}
真正的实例化工作委托给 PostProcessorRegistrationDelegate#registerBeanPostProcessors() 方法:
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
在该方法内部获取到所有的 BeanPostProcessor,然后按照优先级、不同的分类完成实例化。
依赖注入
以常见的单例 Bean 为例,单例 Bean 的初始化同样是在 org.springframework.context.support.AbstractApplicationContext#refresh() 方法中完成:
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// --snip--
try {
// --snip--
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
}
}
}
在 finishBeanFactoryInitialization() 方法中又调用了 preInstantiateSingletons() 方法:
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// --snip--
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
}
最终来到 DefaultListableBeanFactory#preInstantiateSingletons() 方法里:
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() 方法:
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
在 doGetBean() 中创建单例 Bean:
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() 方法,总之就是套娃:
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,也就是进行依赖注入:
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 就是它们中的一员:
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--
}
AutowiredAnnotationBeanPostProcessor 的 postProcessProperties() 方法中,先获取到 InjectionMetadata(注入元数据),然后执行 inject() 方法完成注入:
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() 方法:
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() 方法完成:
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 三种注解:
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 对象被整合到 InjectionMetadata 的 injectedElements 字段中。
完成 InjectionMetadata 对象的组装后,回到 AutowiredAnnotationBeanPostProcessor#postProcessProperties() 方法中,接下来执行 inject() 方法完成依赖注入:
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 类型,也就是会执行到 AutowiredFieldElement 的 inject() 方法:
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() 方法,在该方法中调用 BeanFactory 的 resolveDependency() 方法来获取依赖注入的值:
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() 方法:
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() 方法,获取依赖注入的候选值,根据候选值信息来到最终应该被依赖注入的值:
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 注解进行依赖注入时可以在 beanDefinitionNames 和 resolvableDependencies 搜索要被注入的值。
3. ApplicationContextAware 接口
3.1 接口介绍
ApplicationContextAware 接口是 Aware 接口的子接口,Aware 接口是一个标记接口,类似于 Serializable 接口。实现了 Aware 接口的 Bean 能够通过一个回调方法被 Spring 容器通知(这个「通知」通常用来设置一些 Spring 相关的信息,因此回调方法通常以 set 开头,具体内容由各子接口确定),比如 EnvironmentAware、ApplicationEventPublisherAware 等接口,以及这里的 ApplicationContextAware 接口。
public interface ApplicationContextAware extends Aware {
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
3.2 使用示例
@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 初始化前执行。
@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() 方法。
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() 方法中:
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// --snip--
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
// --snip--
}
}
而在 prepareBeanFactory() 方法中有:
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:
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() 方法呢?
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 接口可以进行更多的自定义逻辑。