Spring的Aware机制原理与应用

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实例化后,初始化前被调用。这里面的逻辑很简单。

  1. 如果当前的bean不是实现Aware接口的类,直接返回;
  2. 如果没有安全检查机制,直接调用invokeAwareInterfaces方法;
  3. 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能有个区别,再深层次的考虑没能领会到,希望大佬赐教。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值