Spring对Aware接口的处理

Spring 中定义了一个 Aware 接口,用于表示一个 bean 可以通过回调的方式接收 Spring 容器的通知。该接口并未定义具体的方法,而是交给子类决定,通常只包含一个只接收单个入参并且返回结果为 void 的方法。

普通的 BeanFactory 包含了 BeanNameAware、BeanClassLoaderAware、BeanFactoryAware 等 Aware 的子接口,如下图所示:

image-20200403020619227

Aware 接口使用示例

如下代码定义了一个 TestAware 类,它实现了 BeanFactoryAware 接口。把 TestAware 注册到 Spring 中,这样就可以获取到当前容器对应的 BeanFactory,然后进行一些操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
public class TestAware implements BeanFactoryAware {
private BeanFactory beanFactory;

@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}

public void doSomething() {
// 可以获取到 beanFactory 进行一些操作
// 比如从获取 bean 实例等等
}
}

类似地,BeanNameAware 接口可用于获取到 bean name,BeanClassLoaderAware 可用于获取到加载 bean 的 class loader。

Aware 接口是在何时回调的

为了便于理解,我们先来看下 Spring 创建 bean 的流程,整体的创建流程如下图所示:

image-20200402015737100

该流程对应 AbstractAutowireCapableBeanFactory 的 doCreateBean 方法

  1. 首先是创建 bean 实例,并且封装为 BeanWrapper 对象。注意这里说的 bean 实例还未初始化,仅仅是通过调用构造方法创建的空对象
  2. 对 RootBeanDefinition(也就是 MergedBeanDefintion)应用 MergedBeanDefinitionPostProcessor。这是 Spring 保留的一个扩展点,可用于对 MergedBeanDefintion 进行操作,以便后续对 bean 属性进行扩展操作
  3. 保存 bean 实例到 singletonFactories 中。这可以用于解决 singleton bean 的循环依赖问题,在后续创建 bean 过程中,注入属性值时可以从 singletonFactories 中获取到未初始化的 bean,从而使得依赖环有了终止条件,进而解决此问题。
  4. 填充 bean 属性。这一步不处理 Aware 接口的注入。
  5. 初始 bean。

Aware 接口是在 initliazeBean 阶段处理的,并且是在对 Bean 进行初始化之前,这样在初始化时就可以用到 Aware 接口的设置结果。下面来看下 Aware 接口的回调

普通 BeanFactory 的 Aware 接口

在进入到 initliazeBean 阶段时,首先会回调 BeanNameAware、BeanClassLoaderAware、BeanFactoryAware 接口方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}

其他 Aware 接口

在 invokeAwareMethods 和 invokeInitMethods 之间会调用 BeanPostProcessor 的 postProcessBeforeInitialization 方法,这一步可用于回调其他 Aware 接口。

例如 ApplicationContext 通过 ApplicationContextAwareProcessor 来回调各种 Aware 接口,它的 postProcessBeforeInitialization 方法实现如下:

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
public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
// 忽略权限控制代码

invokeAwareInterfaces(bean);

return bean;
}

private void invokeAwareInterfaces(Object bean) {
if (bean instanceof Aware) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
}
if (bean instanceof MessageSourceAware) {
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
}

ignoreDependencyInterface

Aware 接口由容器单独管理,通过调用对应的 set 方法设置相应属性。

例如 BeanFactoryAware 通过以下方式调用:

1
2
3
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}

这样可以确保设置的 BeanFactory 为当前容器对应的 BeanFactory。

忽略依赖接口

因为 BeanFactoryAware 接口的 set 注入已经由容器处理,所以在通过 autowireByName 和 autowireByType 注入时无需处理。具体的实现方式是将 BeanFactoryAware 接口添加到 ignoredDependencyInterfaces 中。

autowireByName 和 autowireByType 只会处理符合条件的 propertyNames

1
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);

unsatisfiedNonSimpleProperties 实现如下,它会调用 isExcludedFromDependencyCheck 排除不符合条件的属性

1
2
3
4
5
6
7
8
9
10
11
12
protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {
Set<String> result = new TreeSet<>();
PropertyValues pvs = mbd.getPropertyValues();
PropertyDescriptor[] pds = bw.getPropertyDescriptors();
for (PropertyDescriptor pd : pds) {
if (pd.getWriteMethod() != null && !isExcludedFromDependencyCheck(pd) && !pvs.contains(pd.getName()) &&
!BeanUtils.isSimpleProperty(pd.getPropertyType())) {
result.add(pd.getName());
}
}
return StringUtils.toStringArray(result);
}

isExcludedFromDependencyCheck 调用 AutowireUtils.isSetterDefinedInInterface 方法排除接口

1
2
3
4
5
protected boolean isExcludedFromDependencyCheck(PropertyDescriptor pd) {
return (AutowireUtils.isExcludedFromDependencyCheck(pd) ||
this.ignoredDependencyTypes.contains(pd.getPropertyType()) ||
AutowireUtils.isSetterDefinedInInterface(pd, this.ignoredDependencyInterfaces));
}

BeanFactory 的处理

BeanFactory 默认会忽略 BeanNameAware、BeanClassLoaderAware、BeanFactoryAware 三个接口,它是在 AbstractAutowireCapableBeanFactory 中处理的。在创建 AbstractAutowireCapableBeanFactory 时,构造函数中会调用 ignoreDependencyInterface 添加忽略的依赖接口

1
2
3
4
5
6
public AbstractAutowireCapableBeanFactory() {
super();
ignoreDependencyInterface(BeanNameAware.class);
ignoreDependencyInterface(BeanFactoryAware.class);
ignoreDependencyInterface(BeanClassLoaderAware.class);
}
1
2
3
public void ignoreDependencyInterface(Class<?> ifc) {
this.ignoredDependencyInterfaces.add(ifc);
}

ApplicationContext 的处理

ApplicationContext 还会忽略 EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware 接口,它是在 AbstractApplicationContext 中处理的。具体是在 refresh 的 prepareBeanFactory 阶段,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 忽略其他逻辑

beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

// 忽略其他逻辑
}
}