Spring的Aware机制原理与应用
Spring的Aware在spring框架内部应用的很广泛,学习spring源码时候,经常会发现某个类实现了xxxAware接口。实现xxxAware接口的类其实就是为了能获取相对应的spring对象。今天就来说一下,Aware的是实现原理。
1. 环境搭建
引入依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
创建一个配置类和启动类
@Configuration
public class AppConfig {
}
public class TestSpring {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
}
}
简单的环境搭建完毕。
2. Aware机制应用案例
在spring中Aware是一个空接口,他有几个子接口EnvironmentAware,EmbeddedValueResolverAware,ResourceLoaderAware,ApplicationEventPublisherAware,MessageSourceAware,ApplicationContextAware。这些接口实现原理差不多,每个接口里面都有一个void setXxx(Xxx xxx);方法,为了让实现接口类可以获取Environment,EmbeddedValueResolver,ResourceLoader,ApplicationEventPublisher,MessageSource,ApplicationContext的对象。
下面我就在一个测试类中实现这几个接口。
public class TestAware implements EnvironmentAware, EmbeddedValueResolverAware, ResourceLoaderAware, ApplicationEventPublisherAware, MessageSourceAware, ApplicationContextAware {
private ApplicationContext applicationContext;
private ApplicationEventPublisher applicationEventPublisher;
private StringValueResolver resolver;
private Environment environment;
private MessageSource messageSource;
private ResourceLoader resourceLoader;
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("获取applicationContext:" + applicationContext);
this.applicationContext = applicationContext;
}
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
System.out.println("获取applicationEventPublisher:" + applicationEventPublisher);
this.applicationEventPublisher = applicationEventPublisher;
}
public void setEmbeddedValueResolver(StringValueResolver resolver) {
System.out.println("获取resolver:" + resolver);
this.resolver = resolver;
}
public void setEnvironment(Environment environment) {
System.out.println("获取environment:" + environment);
this.environment = environment;
}
public void setMessageSource(MessageSource messageSource) {
System.out.println("获取messageSource:" + messageSource);
this.messageSource = messageSource;
}
public void setResourceLoader(ResourceLoader resourceLoader) {
System.out.println("获取resourceLoader:" + resourceLoader);
this.resourceLoader = resourceLoader;
}
}
在AppConfig类中填入一下配置
@Bean
public TestAware testAware()
{
return new TestAware();
}
启动TestSpring的main方法,执行结果如下:
获取environment:StandardEnvironment {activeProfiles=[], defaultProfiles=[default], propertySources=[PropertiesPropertySource {name='systemProperties'}, SystemEnvironmentPropertySource {name='systemEnvironment'}]}
获取resolver:org.springframework.beans.factory.config.EmbeddedValueResolver@58fdd99
获取resourceLoader:org.springframework.context.annotation.AnnotationConfigApplicationContext@2e0fa5d3, started on Tue Feb 02 09:12:32 CST 2021
获取applicationEventPublisher:org.springframework.context.annotation.AnnotationConfigApplicationContext@2e0fa5d3, started on Tue Feb 02 09:12:32 CST 2021
获取messageSource:org.springframework.context.annotation.AnnotationConfigApplicationContext@2e0fa5d3, started on Tue Feb 02 09:12:32 CST 2021
获取applicationContext:org.springframework.context.annotation.AnnotationConfigApplicationContext@2e0fa5d3, started on Tue Feb 02 09:12:32 CST 2021
3.Aware机制原理分析
Aware机制的实现原理其实是基于BeanPostProcess后置处理器实现的,从阅读源码的方式分析实现原理。我们都知道在执行AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);代码时,spring会初始化容器。这里面有一个很重要的方法叫refresh();我们就从refresh();方法开始入手。在refresh();方法内部调用了一个叫做prepareBeanFactory(beanFactory);的方法,我们进去这个方法分析。refresh();方法中的其他方法暂时不关心。
//无关的代码已经删掉
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));//添加实现Aware机制的后置处理器
//忽略下面这些接口的依赖注入分析
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
}
这个方法里面我们关注beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));这就代码向spring容器注册了一个ApplicationContextAwareProcessor后置处理器。spring的后置处理器原理不做过多介绍,只说一句,BeanPostProcessor后置处理器的方法会在bean初始化后被容器调用执行。具体原理与应用参考BeanPostProcessor后置处理器原理与应用。
我们去看ApplicationContextAwareProcessor的代码
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){
return bean;
}
AccessControlContext acc = null;
//安全检测机制
if (System.getSecurityManager() != null) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}
if (acc != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareInterfaces(bean);
return null;
}, acc);
}
else {
invokeAwareInterfaces(bean);
}
return bean;
}
private void invokeAwareInterfaces(Object bean) {
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);
}
}
postProcessBeforeInitialization方法会在每个bean实例化后,初始化前被调用。这里面的逻辑很简单。
- 如果当前的bean不是实现Aware接口的类,直接返回;
- 如果没有安全检查机制,直接调用invokeAwareInterfaces方法;
- invokeAwareInterfaces的逻辑就是顺序调用各个Aware接口中setXxx方法,将需要的对象传入。
就这样实现类了xxxAware接口的类,就可以获取xxx对象的实例。
另外提一下,prepareBeanFactory方法还有几个类似的beanFactory.ignoreDependencyInterface(EnvironmentAware.class);方法,其实就是告诉容器在依赖解析自动注入时,忽略xxxAware接口。这里其实很好理解。spring是通过让bean实现xxxAware接口获取相应的对象的实例的,也就没有必要再通过依赖注入的方式获取xxxAware实例的对象了。所以spring容器在一个bean遇到类似一下代码:
@Autowired
private ApplicationEventPublisherAware applicationEventPublisherAware;
spring就不会做自动依赖注入了。我理解spring之所以引入Aware机制就是为了让用户在获取这几个特殊的bean和用户自定义的bean能有个区别,再深层次的考虑没能领会到,希望大佬赐教。