Spring的感知能力 Aware
在 Spring 框架中有一个 org.springframework.beans.factory.Aware 接口,
Aware 是感知感应的意思,那么此接口的作用就是为 Spring 中的 bean 提供了感知外界的能力。
Aware接口本身只是一个标记接口,Spring 中提供了一系列具有具体感知能力的接口,它们都继承自 Aware 接口,
部分如下:
LoadTimeWeaverAware:加载 Spring Bean 时织入第三方模块,如AspectJ
BeanClassLoaderAware:加载 Spring Bean 的类加载器
BootstrapContextAware:资源适配器 BootstrapContext,如JCA,CCI
ResourceLoaderAware:底层访问资源的加载器
BeanFactoryAware:声明 BeanFactory
PortletConfigAware:PortletConfig
PortletContextAware:PortletContext
ServletConfigAware:ServletConfig
ServletContextAware:ServletContext
MessageSourceAware:国际化
ApplicationEventPublisherAware:应用事件
NotificationPublisherAware:JMX通知
BeanNameAware:声明 Spring Bean 的名字
此处以 BeanNameAware 举例,其内部包含了一个 setBeanName 方法,所以当一个 bean 继承了此接口,并定义一个 beanName 的属性,
则在 Spring 容器初始化这个 bean 的时候,会调用这个 setBeanName 方法,注入这个 beanName。
不同的 Aware 注入对应的外界信息的时机是不一样的,具体也分为两类:
1. BeanNameAware/BeanClassLoaderAware/BeanFactoryAware
这三类 Aware 生效的时机是在容器创建 bean 的最后一步完成,具体的调用顺序如下:
getBean(String beanName)
doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
getSingleton(String beanName, ObjectFactory<?> singletonFactory)
在 getSingleton 会回调
createBean(String beanName, RootBeanDefinition mbd, Object[] args)
doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd)
最终在 initializeBean 内会调用如下方法,此处分别调用了对应的 setXXX 方法,外部信息得以注入
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) {
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
2. LoadTimeWeaverAware/ApplicationContextAware/ServletContextAware/MessageSourceAware 等
这一类 Aware 是通过 BeanPostProcessor bean后置处理器实现外部信息注入的。
同样在上述的 initializeBean 方法内会调用如下方法
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException { Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
此处会调用容器中注册的所有的 BeanPostProcessor 的 postProcessBeforeInitialization 方法,而 ApplicationContextAwareProcessor 是默认注册到容器内的,其 postProcessBeforeInitialization 方法内会调用如下方法:
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);
}
}
}
所以 bean 只要继承了 EnvironmentAware,ResourceLoaderAware 就具备相应的感知能力。
最新文章
- fragment嵌套问题
- eclipse真机调试显示Target unknown的解决方法
- 利用vba将excel中的图片链接直接转换为图片
- iOS NSOperation的使用
- [转]Jexus的常用操作和基本配置
- C基础--函数指针的使用
- 彻底理解js中this的指向
- 监控Nginx负载均衡器脚本
- 给方法传递参数:ref参数和out参数
- css中margin:0 auto没作用
- HDU 1686 Oulipo(kmp)
- JS 经典代码段总结 start from 2016-08-22
- [LeetCode] Is Subsequence 题解
- MinGW下简单编译FFmpeg
- javascript this 的工作原理
- CSS之分组选择器和嵌套选择器
- [leetcode]149. Max Points on a Line多点共线
- Java(Java SE7) 体系结构图
- 使用TuShare下载历史逐笔成交数据并生成1分钟线
- WP8.1学习系列(第十九章)——事件和路由事件概述