zoukankan      html  css  js  c++  java
  • 【Spring】Aware 接口原理(九)

    一、Aware 接口介绍

      Aware接口从字面上翻译过来是感知捕获的含义。单纯的bean(未实现Aware系列接口)是没有知觉的;实现了Aware系列接口的bean可以访问Spring容器。这些Aware系列接口增强了Spring bean的功能,但是也会造成对Spring框架的绑定,增大了与Spring框架的耦合度。(Aware是“意识到的,察觉到的”的意思,实现了Aware系列接口表明:可以意识到、可以察觉到)

      代码:

    1 public interface Aware {
    2 
    3 }

    二、Aware 接口扩展点图

      

    三、Aware 接口实现原理

    1、在Spring中,获取bean时,初始化bean

      context.getBean()->doGetBean()->createBeat()->doCreateBeat()->initializeBean()

      initializeBean() 方法如下:

     1 protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
     2     if (System.getSecurityManager() != null) {
     3         AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
     4             invokeAwareMethods(beanName, bean);
     5             return null;
     6         }, getAccessControlContext());
     7     } else {
     8         // 若bean实现了XXXAware接口进行方法的回调
     9         invokeAwareMethods(beanName, bean);
    10     }
    11 
    12     Object wrappedBean = bean;
    13     if (mbd == null || !mbd.isSynthetic()) {
    14         // 支持初始化前bean的后置处理器
    15         wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    16     }
    17 
    18     try {
    19         // 调用初始化方法
    20         invokeInitMethods(beanName, wrappedBean, mbd);
    21     } catch (Throwable ex) {
    22         throw new BeanCreationException(
    23                 (mbd != null ? mbd.getResourceDescription() : null),
    24                 beanName, "Invocation of init method failed", ex);
    25     }
    26     if (mbd == null || !mbd.isSynthetic()) {
    27         wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    28     }
    29 
    30     return wrappedBean;
    31 }

    2、调用了invokeAwareMethods() 方法
      如果bean实现了Aware接口,就能够执行对应Aware接口的方法

     1 private void invokeAwareMethods(final String beanName, final Object bean) {
     2     if (bean instanceof Aware) {
     3         // bean实现了BeanNameAware
     4         if (bean instanceof BeanNameAware) {
     5             ((BeanNameAware) bean).setBeanName(beanName);
     6         }
     7         // 实现了BeanClassLoaderAware接口
     8         if (bean instanceof BeanClassLoaderAware) {
     9             ClassLoader bcl = getBeanClassLoader();
    10             if (bcl != null) {
    11                 ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
    12             }
    13         }
    14         // 实现了BeanFactoryAware
    15         if (bean instanceof BeanFactoryAware) {
    16             ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
    17         }
    18     }
    19 }

    3、支持初始化前bean的后置处理器

      调用了方法applyBeanPostProcessorsBeforeInitialization(),由于内置在创建了ApplicationContextAwareProcessor后置处理器,那么就会调用此后置处理器的方法

      ApplicationContextAwareProcessor#postProcessBeforeInitialization()如下:

     1 // 初始化前调用 此Bean后置处理器处理
     2 @Override
     3 @Nullable
     4 public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
     5     if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
     6             bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
     7             bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){
     8         return bean;
     9     }
    10 
    11     AccessControlContext acc = null;
    12 
    13     // 获取系统安全管理器,默认获取为空
    14     if (System.getSecurityManager() != null) {
    15         acc = this.applicationContext.getBeanFactory().getAccessControlContext();
    16     }
    17 
    18     if (acc != null) {
    19         AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
    20             // 调用Aware接口
    21             invokeAwareInterfaces(bean);
    22             return null;
    23         }, acc);
    24     }
    25     else {
    26         invokeAwareInterfaces(bean);
    27     }
    28 
    29     return bean;
    30 }

    4、后置处理逻辑中调用了invokeAwareInterfaces方法()

     1 // 调用Aware接口
     2 private void invokeAwareInterfaces(Object bean) {
     3     // 判断 bean 属于那种类型,调用对应的方法
     4     if (bean instanceof EnvironmentAware) {
     5         ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
     6     }
     7     if (bean instanceof EmbeddedValueResolverAware) {
     8         ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
     9     }
    10     if (bean instanceof ResourceLoaderAware) {
    11         ((ResourceLoaderAware) bean).    (this.applicationContext);
    12     }
    13     if (bean instanceof ApplicationEventPublisherAware) {
    14         ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
    15     }
    16     if (bean instanceof MessageSourceAware) {
    17         ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
    18     }
    19     if (bean instanceof ApplicationContextAware) {
    20         ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
    21     }
    22 }
  • 相关阅读:
    NOIP2009 pj
    数星星(POJ2352 star)
    洛谷 p3372 模板-线段树 1
    Luogu P1198 [JSOI2008]最大数 线段树
    Bestcoder#92&HDU 6017 T3 Girl loves 233 DP
    NOIP2008pj & luoguP1058 立体图 模拟
    NOIP2003TG 加分二叉树 区间DP
    Redis Jedis lua脚本
    Mac Ideal 常用快捷键
    Mysql慢查询explain
  • 原文地址:https://www.cnblogs.com/h--d/p/14660538.html
Copyright © 2011-2022 走看看