8. 定义标记类型Aware接口,实现感知容器对象
8. 定义标记类型Aware接口,实现感知容器对象
工程结构
lqf-spring-step-08
├── main
│ ├── java
│ │ └── lqf
│ │ └── springframework
│ │ ├── beans
│ │ │ ├── BeansException.java
│ │ │ ├── PropertyValue.java
│ │ │ ├── PropertyValues.java
│ │ │ └── factory
│ │ │ ├── Aware.java
│ │ │ ├── BeanClassLoaderAware.java
│ │ │ ├── BeanFactory.java
│ │ │ ├── BeanFactoryAware.java
│ │ │ ├── BeanNameAware.java
│ │ │ ├── ConfigurableListableBeanFactory.java
│ │ │ ├── DisposableBean.java
│ │ │ ├── HierarchicalBeanFactory.java
│ │ │ ├── InitializingBean.java
│ │ │ ├── ListableBeanFactory.java
│ │ │ ├── config
│ │ │ │ ├── AutowireCapableBeanFactory.java
│ │ │ │ ├── BeanDefinition.java
│ │ │ │ ├── BeanFactoryPostProcessor.java
│ │ │ │ ├── BeanPostProcessor.java
│ │ │ │ ├── BeanReference.java
│ │ │ │ ├── ConfigurableBeanFactory.java
│ │ │ │ └── SingletonBeanRegistry.java
│ │ │ ├── support
│ │ │ │ ├── AbstractAutowireCapableBeanFactory.java
│ │ │ │ ├── AbstractBeanDefinitionReader.java
│ │ │ │ ├── AbstractBeanFactory.java
│ │ │ │ ├── BeanDefinitionReader.java
│ │ │ │ ├── BeanDefinitionRegistry.java
│ │ │ │ ├── CglibSubclassingInstantiationStrategy.java
│ │ │ │ ├── DefaultListableBeanFactory.java
│ │ │ │ ├── DefaultSingletonBeanRegistry.java
│ │ │ │ ├── DisposableBeanAdapter.java
│ │ │ │ ├── InstantiationStrategy.java
│ │ │ │ └── SimpleInstantiationStrategy.java
│ │ │ └── xml
│ │ │ └── XmlBeanDefinitionReader.java
│ │ ├── context
│ │ │ ├── ApplicationContext.java
│ │ │ ├── ApplicationContextAware.java
│ │ │ ├── ConfigurableApplicationContext.java
│ │ │ └── support
│ │ │ ├── AbstractApplicationContext.java
│ │ │ ├── AbstractRefreshableApplicationContext.java
│ │ │ ├── AbstractXmlApplicationContext.java
│ │ │ ├── ApplicationContextAwareProcessor.java
│ │ │ └── ClassPathXmlApplicationContext.java
│ │ ├── core
│ │ │ └── io
│ │ │ ├── ClassPathResource.java
│ │ │ ├── DefaultResourceLoader.java
│ │ │ ├── FileSystemResource.java
│ │ │ ├── Resource.java
│ │ │ ├── ResourceLoader.java
│ │ │ └── UrlResource.java
│ │ └── util
│ │ └── ClassUtils.java
│ └── resources
└── test
├── java
│ └── lqf
│ └── springframework
│ ├── SpringTest.java
│ ├── UserDao.java
│ ├── UserService.java
│ └── common
│ ├── MyBeanFactoryPostProcessor.java
│ └── MyBeanPostProcessor.java
└── resources
├── important.properties
├── spring.xml
└── springPostProcessor.xml
Spring 感知接口的设计和实现类关系,如图:

- 以上整个类关系就是关于 Aware 感知的定义和对容器感知的实现。
- Aware 有四个继承的接口,其他这些接口的继承都是为了继承一个标记,有了标记的存在更方便类的操作和具体判断实现。
- 另外由于 ApplicationContext 并不是在 AbstractAutowireCapableBeanFactory 中 createBean
方法下的内容,所以需要像容器中注册addBeanPostProcessor,再由 createBean 统一调用
applyBeanPostProcessorsBeforeInitialization 时进行操作。
设计
如果说希望拿到 Spring 框架中一些提供的资源,那么首先需要考虑以一个什么方式去获取,之后你定义出来的获取方式,在 Spring
框架中该怎么去承接,实现了这两项内容,就可以扩展出你需要的一些属于 Spring 框架本身的能力了。
在关于 Bean 对象实例化阶段我们操作过一些额外定义、属性、初始化和销毁的操作,其实我们如果像获取 Spring 一些如
BeanFactory、ApplicationContext 时,也可以通过此类方式进行实现。那么我们需要定义一个标记性的接口,这个接口不需要有方法,它只起到标记作用就
可以,而具体的功能由继承此接口的其他功能性接口定义具体方法,最终这个接口就可以通过 instanceof 进行判断和调用了。整体设计结构如下图:

- 定义接口 Aware,在 Spring 框架中它是一种感知标记性接口,具体的子类定义和实现能感知容器中的相关对象。
- 继承 Aware 的接口包括:BeanFactoryAware、BeanClassLoaderAware、BeanNameAware和ApplicationContextAware,当然在 Spring
源码中还有一些其他关于注解的,不过目前还用不到。 - 在具体的接口实现过程中你可以看到,一部分(BeanFactoryAware、BeanClassLoaderAware、BeanNameAware)在 factory 的 support
文件夹下,另外 ApplicationContextAware 是在 context 的 support 中,这是因为不同的内容获取需要在不同的包下提供。所以,在
AbstractApplicationContext 的具体实现中会用到向 beanFactory 添加 BeanPostProcessor
内容的ApplicationContextAwareProcessor操作,最后由 AbstractAutowireCapableBeanFactory 创建 createBean 时处理相应的调用操作。
实现
定义标记接口
源码: lqf.springframework.beans.factory.Aware
- 在 Spring 中有特别多类似这样的标记接口的设计方式,它们的存在就像是一种标签一样,可以方便统一摘取出属于此类接口的实现类,通常会有
instanceof 一起判断使用。
容器感知类
源码1: lqf.springframework.beans.factory.BeanFactoryAware
- Interface to be implemented by beans that wish to be aware of their owning {@link BeanFactory}.
- 实现此接口,既能感知到所属的 BeanFactory
源码2: lqf.springframework.beans.factory.BeanClassLoaderAware
- Callback that allows a bean to be aware of the bean{@link ClassLoader class loader}; that is, the class loader used by
the present bean factory to load bean classes. - 实现此接口,既能感知到所属的 ClassLoader
源码3: lqf.springframework.beans.factory.BeanNameAware
- Interface to be implemented by beans that want to be aware of their bean name in a bean factory.
- 实现此接口,既能感知到所属的 BeanName
源码4: lqf.springframework.context.ApplicationContextAware
- Interface to be implemented by any object that wishes to be notified of the {@link ApplicationContext} that it runs
in. - 实现此接口,既能感知到所属的 ApplicationContext
包装处理器(ApplicationContextAwareProcessor)
源码: lqf.springframework.context.support.ApplicationContextAwareProcessor
- 由于 ApplicationContext 的获取并不能直接在创建 Bean 时候就可以拿到,所以需要在 refresh 操作时,把 ApplicationContext
写入到一个包装的 BeanPostProcessor 中去,再由
AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization 方法调用。
注册 BeanPostProcessor
源码: lqf.springframework.context.support.AbstractApplicationContext#refresh
- 在 refresh() 方法中,需要把 ApplicationContextAwareProcessor 注册到 BeanFactory 中去,这样在 createBean
方法中,就可以调用 applyBeanPostProcessorsBeforeInitialization 方法,执行 ApplicationContextAwareProcessor 的
postProcessBeforeInitialization 方法,从而实现对 ApplicationContext 的感知。
感知调用操作
源码1: lqf.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
源码2: lqf.springframework.beans.factory.support.AbstractBeanFactory
- 首先在 initializeBean 中,通过判断
bean instanceof Aware
,调用了三个接口方法,BeanFactoryAware.setBeanFactory(this)、BeanClassLoaderAware.setBeanClassLoader(getBeanClassLoader())、BeanNameAware.setBeanName(beanName)
,这样就能通知到已经实现了此接口的类。 - 另外还向 BeanPostProcessor 中添加了
ApplicationContextAwareProcessor,此时在这个方法中也会被调用到具体的类实现,得到一个
ApplicationContext 属性。
总结
-
目前关于 Spring 框架的实现中,某些功能点已经越来趋向于完整,尤其是 Bean 对象的生命周期,已经有了很多的体现。整体总结如图:

-
本章节关于 Aware 的感知接口的四个继承接口 BeanNameAware, BeanClassLoaderAware, ApplicationContextAware,
BeanFactoryAware 的实现,又扩展了 Spring 的功能。