读完这篇文章你将会收获到
我们在 ``getBean
` 流程中曾经谈到过
`Spring
` 回调
`Aware
`` 接口
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
`` 接口
public interface Aware {
}
复制代码
一个空的接口、啥都没有、看注释说它只是一个标志性的接口、实现该接口的 ``bean
` 会被
`Spring
`` 以回调的方式进行通知、告诉你某个阶段某件事情发生了
BeanNameAware
public interface BeanNameAware extends Aware {
void setBeanName(String name);
}
复制代码
这个我们举两个有意思的例子,一个是内部 ``bean
` 、一个是
`factoryBean
``
<bean id="customer" class="com.demo.aware.Customer">
<constructor-arg name="person">
<bean class="com.demo.aware.Person">
<property name="name" value="coderLi"/>
<property name="address" value="china"/>
<property name="age" value="666"/>
</bean>
</constructor-arg>
</bean>
<bean id="cat" class="com.demo.aware.CatFactory"/>
复制代码
具体的类就不贴了、没啥逻辑、``CatFactory
` 就实现了
`Spring
` 提供的
`FactoryBean
` 接口。然后我们在
`Person
` 和
`CatFactory
` 中实现了接口
`BeanNameAware
` 、并打印其参数
`name
``
Resource resource = new ClassPathResource("aware/coderLi.xml");
DefaultListableBeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(defaultListableBeanFactory);
xmlBeanDefinitionReader.loadBeanDefinitions(resource);
defaultListableBeanFactory.getBean("customer");
defaultListableBeanFactory.getBean("cat");
复制代码
打印的结果就是:
bean Name aware [bean Name is] :com.demo.aware.Person#71a794e5
bean Name aware [bean Name is] :cat
复制代码
我们打断点在它们 ``getBean
`` 之后,针对下面图片的结果你是否有疑惑呢
第一个是内部 ``bean
`
`Person
` 对象不在
`Spring
` 的容器中、但是它却触发了
`Aware
` 接口的回调 , 第二个是第一级缓存和
`beanFactory
` 缓存中
`key
` 都是
`cat
``
第一个问题其实很简单、主要是构建 ``Customer
` 的构造函数的参数
`Person
` 的时候、在
`BeanDefinitionValueResolver#resolveInnerBean
` 中直接调用了
`createBean
` 方法、然后就到了
`doCreateBean
` 、之后就回调
`Aware
` 接口、但是没用放到
`Spring
`` 容器中
第二个问题、其实两者的 ``key
` 一样是完全没有问题的、往前翻我分析
`getBean
`` 流程的文章可以知道。这里就不重复了
其他
至于 ``BeanClassLoaderAware
` 和
`BeanFactoryAware
`` 就不演示代码了、挺简单的使用。
``Spring
` 里面比较常见的
`Aware
`` 接口
我们看到很多像 ``ApplicationContextAware
` 或者
`EnvironmentAware
` 的
`Aware
` 接口、并没有在
`invokeAwareMethods
` 中被调用到、因为其实这些都是在使用
`ApplicationContext
`` 的时候才会被触发的、具体是在哪里被触发调用呢?
我们可以看到 ``ApplicationContextAwareProcessor#invokeAwareInterfaces
``
中就写了这么一段代码
private void invokeAwareInterfaces(Object bean) {
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);
}
}
复制代码
``ApplicationContextAwareProcessor
` 实现了
`BeanPostProcessor
`` 的、
那这样子的话就是在 ``doCreateBean
` 的时候、通过
`initializeBean
`` 进行回调了
那这个 ``ApplicationContextAwareProcessor
` 什么时候添加到
`Spring
`` 中啊
而这个方法则是在 ``refresh
` 方法中被调用了,而
`refresh
`` 的调用就不用介绍了把
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
复制代码
其实 ``Spring
` 挺有意思的、将这个
`ApplicationContextAwareProcessor
` 作为其第一个
`BeanPostProcessor
` 接口、那么就能保证
`Aware
` 接口被先回调、然后才到用户的
`BeanPostProcessor
`` 实现类
评论