在使用Spring的过程中比较好的设计是bean不依赖于容器。在一些特殊的情况下需要感知容器的存在,使用容器的提供的资源。Spring IoC容器提供了Aware机制。
Aware:意识,发现的意思。它的作用即是让bean感知到容器的资源。早年版本的Spring容器如果需要ApplicationContext则经常使用如下代码去先存储其引用,在容器初始化后手动调用setApplicationContext把引用set进去。
public class ApplicationContextHolder {
private static ApplicationContext applicationContext = null;
public static void setApplicationContext(ApplicationContext applicationContext) { ApplicationContextHolder.applicationContext = applicationContext; }
public static ApplicationContext getApplicationContext() { return applicationContext; }}
如果是web场景下使用ContextLoaderListener来默认初始化容器,取得就有点困难。如果使用Spring的Aware机制则无需自己手动去获得容器的资源,而是Spring容器初始化bean后对其进行注入。上述例子可以修改为
@Componentpublic class ApplicationContextHolder implements ApplicationContextAware {
private ApplicationContext applicationContext;
@Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; }
public ApplicationContext getApplicationContext() { return applicationContext; }}
ApplicationContextHolder的applicationContext不再是一个静态字段。当然并不希望到处去使用ApplicationContextHolder而是需要使用到ApplicationContext的时候bean自己去ApplicationContextAware。
除了ApplicationContextAware,Spring容器还默认提供了一些常用的容器相关对象发现接口。
public class AwareBean implements ApplicationContextAware, ApplicationEventPublisherAware, BeanClassLoaderAware, BeanFactoryAware, MessageSourceAware, BeanNameAware {
@Override public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { // 获得ApplicationEventPublisher, // 可使用来发布Spring容器事件 }
@Override public void setBeanClassLoader(ClassLoader classLoader) { // 动态bean初始化的时候使用和Spring容器一样的ClassLoader }
@Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { // 获得 BeanFactory }
@Override public void setBeanName(String beanName) { // 获得当前bean的名称 }
@Override public void setMessageSource(MessageSource messageSource) { // i18n和一些配置参数解析 }
@Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { // 获得 ApplicationContext }}
Spring容器提供了Aware机制,使Bean能够感知到容器的资源。此功能虽然是比较方便,但是使得Bean依赖于容器的API,这违背了依赖反转的初衷。因此,只有在一些需要对容器进行动态编程的基础bean才建议使用。