Spring Aware原理

Posted work hard work smart

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Aware原理相关的知识,希望对你有一定的参考价值。

上一篇中Spring Boot 属性配置中的启动类加载器有实现EnvironmentAware接口,这里我们就介绍下Spring Aware

一、Aware介绍

Spring框架有点: Bean感知不到容器的存在

使用场景: 需要使用Spirng容器的功能资源

引入缺点: Bean和容器强耦合

 

二、常用Aware

类名 作用
BeanNameAware 获取容器中bean名称
BeanClassLoaderAware 获得类加载器
BeanFactoryAware 获得bean创建工厂
EnviromentAware 获得环境变量
EnvironmentValueResolverAware 获取spring容器加载的properties文件属性值
ResourceLoaderAware 获得资源加载器
ApplicationEventPublisherAware   获得应用程序发布器
MessageSourceAware 获得文本信息
ApplicationContextAware   获得当前应用上下文



 

 

 

 

 

 

 










三、Aware调用原理
我们以ResultCommandLineRunner启动类加载器为例。实现了EnvironmentAware接口,目的就是为了获得environment,从而打印属性
@Component
public class ResultCommandLineRunner implements CommandLineRunner, EnvironmentAware , MyAware{

    private Environment env;

    private  Flag flag;

    @Override
    public void run(String... args) throws Exception {
        System.out.println(flag.isCanOperate());
        System.out.println(env.getProperty("weburl"));
        System.out.println(env.getProperty("weburl.random"));
        System.out.println(env.getProperty("weburl.vm.name"));
    }

    @Override
    public void setEnvironment(Environment environment) {
        this.env = environment;
    }

    @Override
    public void setFlag(Flag flag) {
        this.flag = flag;
    }
}

    

1、Debug运行程序,定位到initializeBean方法

 


2、进入initializeBean。beanName为resultCommandLineRunner(可以根据beanName设置条件断点)

下面是initializeBean的方法

 

 

3、进入postProcessBeforeInitialization方法

 

 

 

4、进入ApplicationContextAwareProcessor类的invokeAwareInterfaces方法

 

 

5、然后就进入了setEnvironment方法,参数为environment。

 

 这就是通过启动类加载器,实现EnvironmentAware,从而获得Environment的流程

 

 四、模拟创建自定义Aware

1、创建Flag类

@Component
public class Flag
{
    private boolean canOperate = true;

    public boolean isCanOperate() {
        return canOperate;
    }

    public void setCanOperate(boolean canOperate) {
        this.canOperate = canOperate;
    }
}

  

2、创建自定义Aware接口,目的就是为了获得Flag。继承Aware接口

public interface MyAware extends Aware{

    void setFlag(Flag flag);
}

  

3、创建处理器

@Component
public class MyAwareProcess implements BeanPostProcessor{

    private final ConfigurableApplicationContext configurableApplicationContext;

    public MyAwareProcess( ConfigurableApplicationContext configurableApplicationContext){
        this.configurableApplicationContext = configurableApplicationContext;
    }

    @Nullable
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if(bean instanceof Aware){
            if(bean instanceof  MyAware){
                ((MyAware)bean).setFlag((Flag) configurableApplicationContext.getBean("flag"));
            }
        }
        return bean;
    }
}

  

4、启动类加载器增加flag变量

@Component
public class ResultCommandLineRunner implements CommandLineRunner, EnvironmentAware , MyAware{

    private Environment env;

    private  Flag flag;

    @Override
    public void run(String... args) throws Exception {
        System.out.println(flag.isCanOperate());
        System.out.println(env.getProperty("weburl"));
        System.out.println(env.getProperty("weburl.random"));
        System.out.println(env.getProperty("weburl.vm.name"));
    }

    @Override
    public void setEnvironment(Environment environment) {
        this.env = environment;
    }

    @Override
    public void setFlag(Flag flag) {
        this.flag = flag;
    }
}

  

5、运行。输出flag为true

 

 


 


以上是关于Spring Aware原理的主要内容,如果未能解决你的问题,请参考以下文章

Spring原理分析-Aware接口&InitializingBean

想减少代码量,快设置一个有感知的 Aware Spring Bean

Spring之Aware

Spring的感知能力 Aware

spring中aware接口的

手写Spring,定义标记类型Aware接口,实现感知容器对象