Spring对Aware接口的处理
Spring 中定义了一个 Aware 接口,用于表示一个 bean 可以通过回调的方式接收 Spring 容器的通知。该接口并未定义具体的方法,而是交给子类决定,通常只包含一个只接收单个入参并且返回结果为 void 的方法。
普通的 BeanFactory 包含了 BeanNameAware、BeanClassLoaderAware、BeanFactoryAware 等 Aware 的子接口,如下图所示:
Aware 接口使用示例
如下代码定义了一个 TestAware 类,它实现了 BeanFactoryAware 接口。把 TestAware 注册到 Spring 中,这样就可以获取到当前容器对应的 BeanFactory,然后进行一些操作。
1 | public class TestAware implements BeanFactoryAware { |
类似地,BeanNameAware 接口可用于获取到 bean name,BeanClassLoaderAware 可用于获取到加载 bean 的 class loader。
Aware 接口是在何时回调的
为了便于理解,我们先来看下 Spring 创建 bean 的流程,整体的创建流程如下图所示:
该流程对应 AbstractAutowireCapableBeanFactory 的 doCreateBean 方法
- 首先是创建 bean 实例,并且封装为 BeanWrapper 对象。注意这里说的 bean 实例还未初始化,仅仅是通过调用构造方法创建的空对象
- 对 RootBeanDefinition(也就是 MergedBeanDefintion)应用 MergedBeanDefinitionPostProcessor。这是 Spring 保留的一个扩展点,可用于对 MergedBeanDefintion 进行操作,以便后续对 bean 属性进行扩展操作
- 保存 bean 实例到 singletonFactories 中。这可以用于解决 singleton bean 的循环依赖问题,在后续创建 bean 过程中,注入属性值时可以从 singletonFactories 中获取到未初始化的 bean,从而使得依赖环有了终止条件,进而解决此问题。
- 填充 bean 属性。这一步不处理 Aware 接口的注入。
- 初始 bean。
Aware 接口是在 initliazeBean 阶段处理的,并且是在对 Bean 进行初始化之前,这样在初始化时就可以用到 Aware 接口的设置结果。下面来看下 Aware 接口的回调
普通 BeanFactory 的 Aware 接口
在进入到 initliazeBean 阶段时,首先会回调 BeanNameAware、BeanClassLoaderAware、BeanFactoryAware 接口方法。
1 | private void invokeAwareMethods(final String beanName, final Object bean) { |
其他 Aware 接口
在 invokeAwareMethods 和 invokeInitMethods 之间会调用 BeanPostProcessor 的 postProcessBeforeInitialization 方法,这一步可用于回调其他 Aware 接口。
例如 ApplicationContext 通过 ApplicationContextAwareProcessor 来回调各种 Aware 接口,它的 postProcessBeforeInitialization 方法实现如下:
1 | public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException { |
ignoreDependencyInterface
Aware 接口由容器单独管理,通过调用对应的 set 方法设置相应属性。
例如 BeanFactoryAware 通过以下方式调用:
1 | if (bean instanceof BeanFactoryAware) { |
这样可以确保设置的 BeanFactory 为当前容器对应的 BeanFactory。
忽略依赖接口
因为 BeanFactoryAware 接口的 set 注入已经由容器处理,所以在通过 autowireByName 和 autowireByType 注入时无需处理。具体的实现方式是将 BeanFactoryAware 接口添加到 ignoredDependencyInterfaces 中。
autowireByName 和 autowireByType 只会处理符合条件的 propertyNames
1 | String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw); |
unsatisfiedNonSimpleProperties 实现如下,它会调用 isExcludedFromDependencyCheck 排除不符合条件的属性
1 | protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) { |
isExcludedFromDependencyCheck 调用 AutowireUtils.isSetterDefinedInInterface 方法排除接口
1 | protected boolean isExcludedFromDependencyCheck(PropertyDescriptor pd) { |
BeanFactory 的处理
BeanFactory 默认会忽略 BeanNameAware、BeanClassLoaderAware、BeanFactoryAware 三个接口,它是在 AbstractAutowireCapableBeanFactory 中处理的。在创建 AbstractAutowireCapableBeanFactory 时,构造函数中会调用 ignoreDependencyInterface 添加忽略的依赖接口
1 | public AbstractAutowireCapableBeanFactory() { |
1 | public void ignoreDependencyInterface(Class<?> ifc) { |
ApplicationContext 的处理
ApplicationContext 还会忽略 EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware 接口,它是在 AbstractApplicationContext 中处理的。具体是在 refresh 的 prepareBeanFactory 阶段,代码如下:
1 | protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { |
- 2020-03-31
当调用 BeanFactory.getBean 方法获取 Bean 时,如果 Bean 还未创建,则会触发 Bean 的创建,本文主要关注 Bean 的创建过程。
- 2020-01-22
XmlBeanFactory 可以说是 Spring 中一个最简单的 BeanFactory,通过它可以了解 Spring 的设计思路。
- 2020-04-11
AbstractApplicationContext
是ApplicationContext
的一个抽象实现类。和普通的BeanFactory
不同的是,ApplicationContext
可以检测到它的内部BeanFactory
中定义的特殊 Bean:自动完成BeanFactoryPostProcessor
、BeanPostProcessor
、ApplicationListener
的注册。 - 2020-04-18
在 dubbo的Reference注解实现原理 中提到,
@Reference
注解用于实现 RPC client 代理的自动注入,这是通过ReferenceAnnotationBeanPostProcessor
来实现的。若要让其生效,还需要在这之前将其注册到 BeanFactory 中。 - 2020-04-16
Spring 通过
AbstractAutoProxyCreator
来创建 AOP 代理,AbstractAutoProxyCreator 是一个抽象类,它实现了BeanPostProcessor
接口,用于在 bean 初始化完成之后创建它的代理