美文网首页IT@程序员猿媛
【Spring 笔记】Aware 接口相关整理

【Spring 笔记】Aware 接口相关整理

作者: 58bc06151329 | 来源:发表于2019-09-29 15:07 被阅读0次

    文前说明

    作为码农中的一员,需要不断的学习,我工作之余将一些分析总结和学习笔记写成博客与大家一起交流,也希望采用这种方式记录自己的学习之旅。

    本文仅供学习交流使用,侵权必删。
    不用于商业目的,转载请注明出处。

    1. 概述

    • 初始化 bean 的方法的调用流程(主要还是根据 用户设定 的来进行初始化)的第一个步骤就是激活 Aware 方法。

    2. Aware 接口

    • org.springframework.beans.factory.Aware 接口。
    public interface Aware {
    }
    
    • Aware 接口为 Spring 容器的核心接口,是一个具有标识作用的接口,实现了该接口的 bean 是具有被 Spring 容器通知的能力,通知的方式是采用 回调 的方式。
    • Aware 接口是一个空接口,实际的方法签名由各个子接口确定。
      • 该接口通常只会有一个接收单参数的 set 方法,该 set 方法的命名方式为 set + 去掉接口名中的 Aware 后缀,即 XxxAware 接口,则方法定义为 setXxx(),例如 BeanNameAware(setBeanName),ApplicationContextAware(setApplicationContext)。
    • Aware 的子接口需要提供一个 setXxx 方法,即 Aware 类接口的 setXxx 方法就是设置 xxx 属性值。

    invokeAwareMethods

    // AbstractAutowireCapableBeanFactory.java
    private void invokeAwareMethods(final String beanName, final Object bean) {
        if (bean instanceof Aware) {
            // BeanNameAware
            if (bean instanceof BeanNameAware) {
                ((BeanNameAware) bean).setBeanName(beanName);
            }
            // BeanClassLoaderAware
            if (bean instanceof BeanClassLoaderAware) {
                ClassLoader bcl = getBeanClassLoader();
                if (bcl != null) {
                    ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
                }
            }
            // BeanFactoryAware
            if (bean instanceof BeanFactoryAware) {
                ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
            }
        }
    }
    
    • 判断 bean 实例是否属于 Aware 接口的范畴,如果是则调用实例的 setXxx() 方法给实例设置 xxx 属性值(主要设置 beanName,beanClassLoader、BeanFactory 中三个属性值)。

    3. Aware 子类

    • Spring 提供了诸多 Aware 接口,用于辅助 Spring Bean 以编程的方式调用 Spring 容器,通过实现这些接口,可以增强 Spring Bean 的功能。
    接口 说明
    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 的名字。

    3.1 用例

    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.BeanClassLoaderAware;
    import org.springframework.beans.factory.BeanFactory;
    import org.springframework.beans.factory.BeanFactoryAware;
    import org.springframework.beans.factory.BeanNameAware;
    import org.springframework.beans.factory.support.DefaultListableBeanFactory;
    import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import org.springframework.core.io.ClassPathResource;
    
    public class Test implements BeanNameAware, BeanFactoryAware, BeanClassLoaderAware, ApplicationContextAware {
    
        private String beanName;
    
        private BeanFactory beanFactory;
    
        private ClassLoader classLoader;
    
        private ApplicationContext applicationContext;
    
        @Override
        public void setBeanClassLoader(ClassLoader classLoader) {
            System.out.println("调用了 BeanClassLoaderAware 的 setBeanClassLoader 方法");
            this.classLoader = classLoader;
        }
    
        @Override
        public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
            System.out.println("调用了 BeanFactoryAware 的 setBeanFactory 方法");
            this.beanFactory = beanFactory;
        }
    
        @Override
        public void setBeanName(String name) {
            System.out.println("调用了 BeanNameAware 的 setBeanName 方法");
            this.beanName = name;
        }
    
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            System.out.println("调用了 ApplicationContextAware 的 setApplicationContext 方法");
            this.applicationContext = applicationContext;
        }
    
        public void display() {
            System.out.println("beanName:" + beanName);
            System.out.println("是否为单例:" + beanFactory.isSingleton(beanName));
            System.out.println("系统环境为:" + applicationContext.getEnvironment());
        }
    
        public static void main(String[] args) {
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
            Test test = (Test) applicationContext.getBean("test");
            test.display();
        }
    }
    
    • Spring 配置文件。
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
        <bean id="test" class="Test"></bean>
    </beans>
    
    • 运行输出。
    调用了 BeanNameAware 的 setBeanName 方法
    调用了 BeanClassLoaderAware 的 setBeanClassLoader 方法
    调用了 BeanFactoryAware 的 setBeanFactory 方法
    调用了 ApplicationContextAware 的 setApplicationContext 方法
    beanName:test
    是否为单例:true
    系统环境为:StandardEnvironment {activeProfiles=[], defaultProfiles=[default], propertySources=[MapPropertySource {name='systemProperties'}, SystemEnvironmentPropertySource {name='systemEnvironment'}]}
    

    相关文章

      网友评论

        本文标题:【Spring 笔记】Aware 接口相关整理

        本文链接:https://www.haomeiwen.com/subject/ljmfpctx.html