前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >「Spring 源码分析」Aware

「Spring 源码分析」Aware

原创
作者头像
花言不知梦
修改2020-05-25 15:34:56
6120
修改2020-05-25 15:34:56
举报
文章被收录于专栏:花言不知梦

Spring Aware

一个空标记接口,表示 bean 可以通过接口定义的回调方法,获取相应的 Spring容器对象 对bean进行处理

源码分析

1. 首先在 实现 EnvironmemtAware接口对象 中的 setEnvironment(Environment environment)方法 打断点,通过堆栈,查看具体 Aware接口 的调用执行顺序,进行源码分析

图1.1 - 调用setEnvironment方法的debug界面中显示所对应的堆栈
图1.1 - 调用setEnvironment方法的debug界面中显示所对应的堆栈

通过堆栈分析,我们可以知道,Aware接口 的调用点有两处

a. AbstractCapableBeanFactory工厂类 的 initializeBean方法 里的 invokeAwareMethods(beanName, bean)方法

b. ApplicationContextAwareProcessor后处理器 的 postProcessBeforeInitialization方法里 invokeAwareInterfaces(bean)方法

第一个调用点是 AbstractCapableBeanFactory工厂类 的 initializeBean方法 里的 invokeAwareMethods(beanName, bean)方法,下面我们对该方法进行分析

该方法处理 Aware接口 的顺序:BeanNameAware -> BeanClassLoaderAware -> BeanFactoryAware

代码语言:java
复制
1. 进入 initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd)方法
   protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
        // 安全管理器模式
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged(() -> {
                this.invokeAwareMethods(beanName, bean);
                return null;
            }, this.getAccessControlContext());
        } else {
            // Aware接口 的第一个调用点
            this.invokeAwareMethods(beanName, bean);
        }

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            // 遍历所有的后处理器,得到ApplicationContextAwareProcessor后处理器,然后执行相应Aware对象处理
            wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
        }

        try {
            this.invokeInitMethods(beanName, wrappedBean, mbd);
        } catch (Throwable var6) {
            throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);
        }

        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }

        return wrappedBean;
    }
2. 进入 this.invokeAwareMethods(beanName, bean)方法
   // 这是对 Aware接口 的直接方法调用
   private void invokeAwareMethods(String beanName, Object bean) {
        // 如果bean是Aware类型(这里指的是实现Aware接口)
        if (bean instanceof Aware) {
            // 如果bean是BeanNameAware类型
            if (bean instanceof BeanNameAware) {
                // 设置bean名称
                ((BeanNameAware)bean).setBeanName(beanName);
            }

            // 如果bean是BeanClassLoaderAware类型
            if (bean instanceof BeanClassLoaderAware) {
                // 获取类加载器
                ClassLoader bcl = this.getBeanClassLoader();
                if (bcl != null) {
                    ((BeanClassLoaderAware)bean).setBeanClassLoader(bcl);
                }
            }
            
            // 如果bean是BeanFactoryAware类型
            if (bean instanceof BeanFactoryAware) {
                // 获取beanFactory工厂
                ((BeanFactoryAware)bean).setBeanFactory(this);
            }
        }

    }

第二个调用点是 ApplicationContextAwareProcessor后处理器 的 postProcessBeforeInitialization方法 里的 invokeAwareInterfaces(bean)方法,下面我们来具体分析不同类型的Aware具体加载了什么

该方法处理 Aware接口 的顺序:EnvironmentAware -> EmbeddedValueResolverAware -> ResourceLoaderAware ->ApplicationEventPublisherAware -> MessageSourceAware -> ApplicationContextAware

代码语言:java
复制
1. 进入 postProcessBeforeInitialization(Object bean, String beanName)方法
   public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
       // 对bean类型进行判断
       if (!(bean instanceof EnvironmentAware) && !(bean instanceof EmbeddedValueResolverAware) && !(bean instanceof ResourceLoaderAware) && !(bean instanceof ApplicationEventPublisherAware) && !(bean instanceof MessageSourceAware) && !(bean instanceof ApplicationContextAware)) {
            return bean;
       } else {
           AccessControlContext acc = null;
           if (System.getSecurityManager() != null) {
               acc = this.applicationContext.getBeanFactory().getAccessControlContext();
           }
            
           // 安全管理器模式
           if (acc != null) {
               AccessController.doPrivileged(() -> {
                   this.invokeAwareInterfaces(bean);
                   return null;
               }, acc);
           } else {
               this.invokeAwareInterfaces(bean);
           }

           return bean;
       }
   }
2. 进入 this.invokeAwareInterfaces(bean)方法
   private void invokeAwareInterfaces(Object bean) {
        if (bean instanceof EnvironmentAware) {
            // 获取 Environment环境变量,可以通过 Environment环境变量 获取属性
            ((EnvironmentAware)bean).setEnvironment(this.applicationContext.getEnvironment());
        }

        if (bean instanceof EmbeddedValueResolverAware) {
            // 获取 Spring容器 加载的 properties文件 里面相应的属性值
            ((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);
        }

        if (bean instanceof ApplicationContextAware) {
            // 获取 ApplicationContext上下文容器
            ((ApplicationContextAware)bean).setApplicationContext(this.applicationContext);
        }

    }

- End -(转载请注明出处)

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档