zoukankan      html  css  js  c++  java
  • 【spring源码分析】IOC容器初始化——查漏补缺(一)

    前言:在【spring源码分析】IOC容器初始化(十一)中提到了初始化bean的三个步骤:

    • 激活Aware方法。
    • 后置处理器应用(before/after)。
    • 激活自定义的init方法。

    这里我们就来看下Spring是如何激活Aware方法的。


    Aware是什么

    Aware是一个空接口,包路径为:org.springframework.beans.factory.Aware,它具有标识作用,实现了该接口的bean具有被Spring容器通知的能力,通知的方式采用回调的方式。

    由于Aware是一个空接口,实际的方法签名由各个子类来确定,其该接口通常只会有一个接收单参数的set方法,该set方法的命名方式为set+去掉接口中的Aware后缀,即:setxxx(),那Spring中是如何处理实现Aware接口的bean的呢。在invokeAwareMethods方法中可以看到如下代码:

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

    分析:

    首先判断bean是否实现了Aware接口,如果是则调用实例的setXXX()方法给实例设置xxx属性,在invokeAwareMethods方法中,主要处理BeanNameAware、BeanClassLoaderAware、BeanFactoryAware三种接口,也从侧面证实了Spring只会处理实现了这三种接口中任意一个的bean实例。

    Aware示例演示

    下面就演示Spring是如何处理实现这三个接口的bean的:

     1 public class UserDefinedAware implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware {
     2 
     3     private String name;
     4     private ClassLoader classLoader;
     5     private BeanFactory beanFactory;
     6 
     7     @Override
     8     public void setBeanName(String name) {
     9         System.out.println("调用了 BeanNameAware 的 setBeanName方法");
    10         this.name = name;
    11     }
    12 
    13     @Override
    14     public void setBeanClassLoader(ClassLoader classLoader) {
    15         System.out.println("调用了 BeanClassLoader 的 setBeanClassLoader 方法");
    16         this.classLoader = classLoader;
    17     }
    18 
    19     @Override
    20     public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
    21         System.out.println("调用了 BeanFactoryAware 的 setBeanFactory 方法");
    22         this.beanFactory = beanFactory;
    23     }
    24 
    25     public void showMsg() {
    26         System.out.println("beanName=" + this.name);
    27         System.out.println("classLoader=" + this.classLoader.getClass());
    28         System.out.println("是否为单例=" + beanFactory.isSingleton(this.name));
    29     }
    30 }

    测试方法如下:

    1     /**
    2      * Aware接口演示
    3      */
    4     @Test
    5     public void awareTest() {
    6         ApplicationContext context = new ClassPathXmlApplicationContext("classpath*:com/dev/config/aware/aware.xml");
    7         UserDefinedAware userDefinedAware = context.getBean(UserDefinedAware.class);
    8         userDefinedAware.showMsg();
    9     }

    输出结果如下:

    Aware总结

    从以上示例基本上可以了解 Aware接口 真正的含义:感知,其实是Spring容器在初始化主动检测当前bean是否实现了Aware接口,如果实现了则回调其set方法将相应的参数设置给该bean,这个时候该bean就从Spring容器中取得了相应的资源。所以Aware接口的作用就是让实现该接口的bean能从Spring容器中取得相应的资源。这里如name、ClassLoader、beanFactory。

    下面列出一些常用的Aware接口,便于日后查询:

    • LoadTimeWeaverAware:加载Spring Bean时织入第三方模块,如AspectJ
    • BeanClassLoaderAware:加载Spring Bean的类加载器
    • BootstrapContextAware:资源适配器BootstrapContext,如JCA,CCI
    • ResourceLoaderAware:底层访问资源的加载器
    • BeanFactoryAware:声明BeanFactory
    • PortletConfigAware:PortletConfig
    • PortletContextAware:PortletContext
    • ServletConfigAware:ServletConfig
    • ServletContextAware:ServletContext
    • MessageSourceAware:国际化
    • ApplicationEventPublisherAware:应用事件
    • NotificationPublisherAware:JMX通知
    • BeanNameAware:获取Spring Bean的名字

    by Shawn Chen,2019.04.29,晚上。

  • 相关阅读:
    Sprite子节点透明度不能跟随父节点变化的问题求解(转)
    cocos2dx模拟器修改窗口大小
    VS中拒绝在if语句中赋值 (转)
    cocos2dx 开启控制台
    (原创)动态内存管理练习 C++ std::vector<int> 模拟实现
    cocos2dx-lua 圆角矩形 圆角图片 drawNode
    cocos2dx-lua 裁剪ClippingNode,圆形头像,其他形状图片
    cocos2dx-lua 文件操作
    (原创)cocos2dx-lua TableView官方demo分析
    lua table表判断是否为空
  • 原文地址:https://www.cnblogs.com/developer_chan/p/10793104.html
Copyright © 2011-2022 走看看