一、Aware接口
代码分支:aware-interface
之前都是基于main分支来追踪源码,从现在开始,我们基于每章开始的代码分支追踪源码。mini-spring源码作者建议如此,这样阅读难度会更小。
Aware是感知、意识的意思,Aware接口是标记性接口,其实现子类能感知容器相关的对象。常用的Aware接口有BeanFactoryAware和ApplicationContextAware,分别能让其实现者感知所属的BeanFactory和ApplicationContext。
让实现BeanFactoryAware接口的类能感知所属的BeanFactory,实现比较简单,查看AbstractAutowireCapableBeanFactory#initializeBean前三行。
实现ApplicationContextAware的接口感知ApplicationContext,是通过BeanPostProcessor。由bean的生命周期可知,bean实例化后会经过BeanPostProcessor的前置处理和后置处理。定义一个BeanPostProcessor的实现类ApplicationContextAwareProcessor,在AbstractApplicationContext#refresh方法中加入到BeanFactory中,在前置处理中为bean设置所属的ApplicationContext。
改用dom4j解析xml文件。
至止,bean的生命周期如下:

测试:
spring.xml
xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<bean id="helloService" class="org.springframework.test.service.HelloService"/>
</beans>
java
public class HelloService implements ApplicationContextAware, BeanFactoryAware {
private ApplicationContext applicationContext;
private BeanFactory beanFactory;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
public ApplicationContext getApplicationContext() {
return applicationContext;
}
public BeanFactory getBeanFactory() {
return beanFactory;
}
}
java
public class AwareInterfaceTest {
@Test
public void test() throws Exception {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring.xml");
HelloService helloService = applicationContext.getBean("helloService", HelloService.class);
assertThat(helloService.getApplicationContext()).isNotNull();
assertThat(helloService.getBeanFactory()).isNotNull();
}
}
二、源码追踪

可以看到HelloService实现了两个接口BeanFactoryAware、ApplicationContextAware。这两个接口都要实现他们各自的方法,分别是设置ApplicationContext、BeanFactory。这两个都是ioc容器。
BeanFactory多用于spring本身,ApplicationContext多用于我们这些使用者。
2.1 BeanFactoryAware源码追踪








DefaultListableBeanFactory对象类图:

2.2 ApplicationContextAware源码追踪
前8步,和【10.1.1】一毛一样,我们从第9步开始看:




2.3 设置完BeanFactory和ApplictionContext之后呢?干了什么
暂时还不懂。
三、应用场景
我有一个类,不归spring管理,但我又想在这个类里操作spring,那么我该如何操作?


3.1 SpringUtil源码:

其中,BeanFactoryPostProcessor是用来修改BeanDefinition的。


3.2 SpringUtil中设计到BeanFactoryPostProcessor部分的源码
实现BeanFactoryPostProcessor接口,需要重写这个方法:

它的入参,要注入一个ConfigurableListableBeanFactory对象。这个其实就是我们前面看到的DefaultListableBeanFactory对象。可以看前面的类图:



这里的对象,就包括了SpringUtil对象!
猜测:
读到这里,我猜测SpringUtil是不是应该被加入到了spring容器里,我猜大概率是通过spi的方式加入进去的。
查看hutool源码,果然印证了我的猜测:

多废话一句,对第【5】步做一个补充:

废话说完了,继续第6步:

只是我们之前自定义的CustomBeanFactoryPostProcessor:

hutool的SpringUtil:
