Spring中的Aware解析
- 2019 年 12 月 30 日
- 筆記
简介
- Spring框架中提供了许多实现了Aware接口的类,这些类主要是为了辅助Spring访问容器中的数据,比如
BeanNameAware
,这个类能够在Spring容器加载的过程中将Bean的名字(id)赋值给变量。
常用的Aware
BeanNameAware
:能够获取bean的名称,即是idBeanFactoryAware
:获取BeanFactory实例ApplicationContextAware
:获取ApplicationContext
MessageSourceAware
:获取MessageSourceResourceLoaderAware
:获取ResourceLoader
EnvironmentAware
:获取Environment
ApplicationContextAware
- ApplicationContext可以获取容器中的bean,但是必须注入才能使用,当一些类不能注入的时候怎么才能获得bean呢?比如Utils中的类,通常不能直接通过注入直接使用ApplicationContext,此时就需要借助
ApplicationContextAware
这个接口了。 ApplicationContextAware
的实现类如下
1234567891011121314151617 |
/** * 自定义一个实现类,一定要注入到容器中 */@Componentpublic class ApplicationContextAwareImpl implements ApplicationContextAware { /** * 容器启动的时候会调用这个方法,只需要将applicationContext设置即可 * @param applicationContext 容器启动会自动注入 * @throws BeansException */ @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { //将其设置到ApplicationContextUtil ApplicationContextUtil.setApplicationContext(applicationContext); }} |
---|
ApplicationContextUtil
如下:
123456789101112131415161718192021222324252627282930313233343536373839 |
import org.springframework.context.ApplicationContext;/** * ApplicationContext的工具类 */public class ApplicationContextUtil { /** * ApplicationContext对象,会ApplicationContextAwareImpl中的setApplicationContext方法中赋值 */ private static ApplicationContext applicationContext; public static ApplicationContext getApplicationContext() { return applicationContext; } public static void setApplicationContext(ApplicationContext applicationContext) { ApplicationContextUtil.applicationContext = applicationContext; } /** * 根据类型获取指定的bean * @param requiredType Class * @param <T> 泛型 * @return */ public static <T> T getBean(Class<T> requiredType ){ return applicationContext.getBean(requiredType); } /** * 根据名称和类型获取Bean * @param name bean的id * @param requiredType class * @param <T> * @return */ public static <T> T getBean(String name,Class<T> requiredType){ return applicationContext.getBean(name,requiredType); }} |
---|
- 配置了如上的工具类,那么就可以直接使用ApplicationContextUtil获取ApplicationContext对象了,而不需要注入了,如下:
1 |
StringRedisTemplate redisTemplate=ApplicationContextUtil.getBean("stringRedisTemplate",StringRedisTemplate.class); |
---|
总结
- spring底层的一些东西并不能通过自动注入直接从ioc容器中获取,但是spring提供了其他的一些方法获取相应的对象,比如一些
Aware
,要向成功获取指定的对象,必备的条件如下:- 实现
xxxAware
接口 - 自定义的类注入到容器中
- 实现
源码解析
- Aware的装配使用的BeanPostProcessor原理,在初始化之前调用set方法设置对应的值,相应的实现都在
org.springframework.context.support.ApplicationContextAwareProcessor#invokeAwareInterfaces
,源码如下:- 主要的逻辑就是判断相应bean的类型,调用相应的set方法1234567891011121314151617181920212223private 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( new EmbeddedValueResolver(this.applicationContext.getBeanFactory())); } 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); } } }