Spring自动装配之Aware注入方式

Spring在进行自动装配时,除了使用常用的注解进行装配之外,如果需要在自定义组件中注入Spring的一些底层组件,例如:BeanFactory,ApplicationContext等,则可以利用Spring提供的一系列Aware接口来完成自动注入。

温馨提示:本博客已经发布小程序,可在微信小程序中搜索”百变码农”,手机上也能看!

1、使用示例

例如给Pen组件中注入Spring的上下文ApplicationContext,并且在Pen组件中获取当前Bean的名称,如下:

a.配置类AutowiredConfig:

/**
 * Created by wangbin33 on 2020/3/8.
 */
@Configuration
@ComponentScan({"com.wb.spring.autowired"})
public class AutowiredConfig {
}

b.Pen类:

/**
 * Created by wangbin33 on 2020/3/8.
 */
@Component
public class Pen implements ApplicationContextAware,BeanNameAware {
   /** 保存Spring容器的引用,如果在本类中其他地方使用,可以直接用 */
   private ApplicationContext applicationContext;

   @Override
   public void setApplicationContext(ApplicationContext 
     applicationContext) throws BeansException {
      System.out.println("当前IOC容器对象为:"+applicationContext);
      this.applicationContext = applicationContext;
   }

   @Override
   public void setBeanName(String name) {
      System.out.println("当前Bean的名称为:" + name);
   }
}

c.测试类TestMain1:

/**
 * Created by wangbin33 on 2020/3/8.
 */
public class TestMain1 {
   public static void main(String[] args) {
      ApplicationContext acx = 
     new AnnotationConfigApplicationContext(AutowiredConfig.class);
      System.out.println(acx);
   }
}

运行结果:

当前Bean的名称为:pen
当前IOC容器对象为:org.springframework.context.annotation.AnnotationConfigApplicationContext@3d646c37, started on Sun Mar 08 15:27:35 CST 2020
org.springframework.context.annotation.AnnotationConfigApplicationContext@3d646c37, started on Sun Mar 08 15:27:35 CST 2020

可以看到,在Pen类中已经获取到了ApplicationContext容器对象和当前bean的名称。

2、底层原理举例解析

在Spring中Aware接口作为一个顶层接口,其底层的xxxAware子接口中全部定义了setxxxAware方法,用于交给具体的类来实现,然后通过xxxAwareProcessor来实现具体的注入。

例如:ApplicationContextAwarePostProcessor源码执行流程如下:

class ApplicationContextAwareProcessor implements BeanPostProcessor {

   private final ConfigurableApplicationContext applicationContext;

   private final StringValueResolver embeddedValueResolver;


   /**
    * Create a new ApplicationContextAwareProcessor for the given context.
    */
   public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
      // 创建Processort的时候,完成applicationContext的赋值
      this.applicationContext = applicationContext;
      // 创建默认的值解析器,用来解析classpath中配置的占位符变量的值
      this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
   }

   // 该方法在创建Bean的过程中,在Bean初始化方法执行完成之后会被调用
   @Override
   @Nullable
   public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
      AccessControlContext acc = null;
      // 获取bean工厂中的AccessControlContext,默认为null
      if (System.getSecurityManager() != null &&
            (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
                  bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
                  bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
         acc = this.applicationContext.getBeanFactory().getAccessControlContext();
      }
      // 由于acc为null,默认该方法不会执行
      if (acc != null) {
         AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
            invokeAwareInterfaces(bean);
            return null;
         }, acc);
      }
      else {
         // 调用Aware接口的方法
         invokeAwareInterfaces(bean);
      }

      return bean;
   }
   // 调用Aware方法
   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);
         }
         // 判断到当前的Bean为ApplicationContextAware的实现类
         if (bean instanceof ApplicationContextAware) {
            // 将Bean向上转型为ApplicationContextAware,并回调其
            //  setApplicationContext方法,然后将ioc对象作为参数传入
            //  在Pen子类中就可以接收到传入的ApplicationContext对象了
            ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
         }
      }
   }
   // 创建Bean的过程中,执行完初始化方法之后,接着会被调用.
   @Override
   public Object postProcessAfterInitialization(Object bean, String beanName) {
      return bean;
   }

}

其他的Aware接口都有对应的Processort后置处理器,用来处理对应的组件注入。

3、Spring中常用的Aware接口及作用

(1)BeanFactoryAware:可以获取用于创建Bean的工厂;

 

(2)BeanNameAware:获取当前bean的名称;

 

(3)ApplicationContextAware:获取当前Bean所在的Spring应用上下文对象,利用该对象可以获取到Spring容器中Bean的很多信息,例如:所有bean的名称,所有bean的定义,bean注册中心等等;

 

(4)MessageSourceAware:用于获取当前应用的国际化信息,包括区域,语言等,在做web应用的国际化时使用;

 

(5)EnvironmentAware:用于获取当前Bean运行的环境信息,例如:操作系统,环境变量,当前classpath中配置的所有property属性值及属性名称等。

注意:上述接口都有对应的Bean的后置处理器,用来完成对应的组件注入功能,名称为xxxAwareProcessor。具体的实现逻辑和ApplicationContextAwareProcessor类似,感兴趣可以自己先阅读相关代码实现,后期会持续更新文章详细介绍Spring各个功能的底层源码实现。

至此,Spring中通过Aware接口注入底层组件的内容介绍完毕!欢迎转发文章!

温馨提示:如果小程序端代码显示混乱,是因为移动端兼容性导致,可移步至PC端站点查看!

文章属于原创,如果转发请标注文章来源:个人小站【www.jinnianshizhunian.vip

另外提供一些优秀的Java架构师及IT开发视频,书籍资料。无需注册,无需登录即可下载,免费下载地址:https://www.592xuexi.com