• Spring Aware接口


    第一次遇见这个接口,是在Bean的初始化过程中。初始化的第一步就是 invokeAwareMethods ,执行Aware子接口的相关set方法。

    网上查资料,大多是术语比如:感知自己的属性。不明白的是,有什么实际应用

    先看抛出一个常见需求,我需要在一个类A里获取一个Bean,但是类A不是一个Bean(不由Spring管理,没办法Autowired来注入其它Bean)。

    那么我们首先要获取到上下文的实例,然后获取任何Bean就不成问题了。

    这个时候我们就可以利用Aware接口的特性来帮助我们获取到ApplicationContext实例了。

    实现Aware接口

    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.BeanNameAware;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;
    
    /**
     * Aware接口的实际应用
     */
    public class ApplicationContextUtils implements ApplicationContextAware,BeanNameAware {
    
        private static ApplicationContext applicationContext;
        private static String name;
    
        /**
         * 设置当前应用程序上下文
         * @param applicationContext
         * @throws BeansException
         */
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            ApplicationContextUtils.applicationContext = applicationContext;
        }
    
        public static <T> T getBean(String name, Class<T> clazz){
            return applicationContext.getBean(name, clazz);
        }
    
        /**
         * 设置当前Bean的名称
         * @param name
         */
        @Override
        public void setBeanName(String name) {
            ApplicationContextUtils.name = name;
        }
    
        public static String getName(){
            return name;
        }
    }

    这里我实现了两个接口,分别“感知”自己的上下文和bean名称

    一个简单实体类

    import lombok.Getter;
    
    @Getter
    public class User {
        private String name = "AAA";
    }

    配置类

    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    
    @Configuration
    public class SimpleConfig {
    
        /**
         * 配置工具类,默认以方法名称为bean名称(实现Aware接口的类要交给Spring管理)
         * @return
         */
        @Bean
        public ApplicationContextUtils applicationContextUtils(){
            return new ApplicationContextUtils();
        }
    
        @Bean("user")
        public User getUser(){
            return new User();
        }
    }

    启动

    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    
    public class Main {
        public static void main(String[] args) throws Exception {
            // 启动容器
            ApplicationContext context = new AnnotationConfigApplicationContext(SimpleConfig.class);
            // 使用工具类来“感知”应用程序上下文,进而手动getBean
            User user = ApplicationContextUtils.getBean("user", User.class);
            System.out.println(user.getName());
            // 感知bean名称
            System.out.println(ApplicationContextUtils.getName());
        }
    }

    输出

    总结

    这么一来,Aware接口的作用就清晰明了了。

    1. Aware接口是个标记接口,标记这一类接口是用来“感知”自己属性的。

    2. Aware的众多子接口则是实现了:我具体要“感知”什么属性

    3. Aware子接口的实现类则是:我要拿到你能“感知”到的属性,为我所用。

    另附Aware子接口

    对于初始化的时候涉及的Aware接口:

    初始化方法全路径:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)

    invokeAwareMethods方法:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeAwareMethods

    这里涉及三个Aware子接口:BeanNameAware、BeanClassLoaderAware、BeanFactoryAware

    实际上另外一些接口

    在容器启动,刷新方法第三步:org.springframework.context.support.AbstractApplicationContext#prepareBeanFactory

    其中有一行:

    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

    后面这个类里有个 postProcessBeforeInitialization 方法,在每个Bean初始化之前调用。

    里面有个 invokeAwareInterfaces 方法

    这里涉及:EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware

  • 相关阅读:
    iframe中的页面如何触发父页面事件
    js获取gridview的值
    不出现重复数字,带干扰的验证码
    文本框内不允许输入字母
    后台调用前台JS方法
    在后台得到前台元素,给元素改变属性值或添加属性
    C#常见面试题
    Flex代码生成器 (FCG)
    c#(WinForm)遍历局域网计算机(电脑)获取IP和计算机名称
    VisualSVN Server + Tortoise SVN 使用教程(补充版)
  • 原文地址:https://www.cnblogs.com/LUA123/p/12362028.html
Copyright © 2020-2023  润新知