spring-beans中Aware相关接口的源码解析说明

Posted mufeng07

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring-beans中Aware相关接口的源码解析说明相关的知识,希望对你有一定的参考价值。

spring版本为5.0.11

Aware是个没有定义任何方法的接口,即标记超接口,拥有众多子接口,在spring源码中有多处都在使用这些子接口完成各种场景下的回调操作。

aware字面意思翻译过来是知道的,感知的,所以理解为感知所有aware前面的含义。

beanNameAware接口(不建议使用):如果某个bean需要访问配置文件中本身bean的id属性,这个Bean类通过实现该接口,在依赖关系确定之后,初始化方法之前,提供回调自身的能力,从而获得本身bean的id属性,该接口提供了void setBeanName(String name)方法实现,需要指出的是该方法的name参数就是该bean的id属性,加调该setBeanName方法可以让bean获取得自身的id属性,这个接口更多的使用在spring的框架代码中,实际开发环境应该不建议使用,因为spring认为bean的名字与bean的联系并不是很深。

BeanFactoryAware接口:实现了BeanFactoryAware接口的bean,可以直接通过beanfactory来访问spring的容器,当该bean被容器创建以后,会有一个相应的beanfactory的实例引用,该 接口有一个方法void setBeanFactory(BeanFactory beanFactory)方法通过这个方法的参数创建它的BeanFactory实例,实现了BeanFactoryAware接口,就可以让Bean拥有访问Spring容器的能力。缺点:导致代码与spring的api耦合在一起,这种方式不推荐。

ApplicationContextAware接口:在Bean类被初始化后,将会被注入applicationContext实例,该接口有一个方法,setApplicationContext(ApplicationContext context),使用其参数context用来创建它的applicationContext实例,缺点:导致代码与spring的api耦合在一起,这种方式不推荐。

MessageSourceAware接口:在Bean中可以得到消息源。

ApplicationEventPublisherAware接口:在bean中可以得到应用上下文的事件发布器,从而可以在Bean中发布应用上下文的事件。

ResourceLoaderAware接口:在Bean中可以得到ResourceLoader,从而在bean中使用ResourceLoader加载外部对应的Resource资源。

 

 

 Aware接口的源码

/**
 * A marker superinterface indicating that a bean is eligible to be notified by the
 * Spring container of a particular framework object through a callback-style method.
 * The actual method signature is determined by individual subinterfaces but should
 * typically consist of just one void-returning method that accepts a single argument.
 *
 * <p>Note that merely implementing {@link Aware} provides no default functionality.
 * Rather, processing must be done explicitly, for example in a
 * {@link org.springframework.beans.factory.config.BeanPostProcessor}.
 * Refer to {@link org.springframework.context.support.ApplicationContextAwareProcessor}
 * for an example of processing specific {@code *Aware} interface callbacks.
 *
 * @author Chris Beams
 * @author Juergen Hoeller
 * @since 3.1
 */
public interface Aware {

}

从源码分析实现Aware接口被调起的原理:

从refresh上下文开始,prepareBeanFactory方法会添加ApplicationContextAwareProcessor后置处理器

 

 

 

触发getBean这个方法,在bean被初始化前,所有bean的后置处理器的postProcessBeforeInitialization方法都会被触发。

 

 

 之前添加ApplicationContextAwareProcessor后置处理器的postProcessBeforeInitialization方法也会被触发

 

 

 如果bean实现了某个接口,那么它的某个对应的方法就会被调用,然而没有BeanNameAware接口和BeanFactoryAware接口

 

 

 AbstractAutowireCapableBeanFactory类的initializeBean方法会调用invokeAwareMethods(beanName, bean)方法

 

 

 

 

 

 以BeanNameAware做个测试:

User1实现了BeanNameAware接口,User没有

public class User {
    private String id;
    private String name;
    private int age;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=\'" + id + \'\\\'\' +
                ", name=\'" + name + \'\\\'\' +
                ", age=" + age +
                \'}\';
    }
}
public class User1 implements BeanNameAware {
    private String id;
    private String name;
    private int age;
    @Override
    public void setBeanName(String s) {
        id=s;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User1{" +
                "id=\'" + id + \'\\\'\' +
                ", name=\'" + name + \'\\\'\' +
                ", age=" + age +
                \'}\';
    }
}

注入

@Configuration
public class TestConfiguration {
    @Bean
    public User user(){
        User user = new User();
        user.setName("zhangsan");
        user.setAge(23);
        return user;
    }
    @Bean
    public User1 user1(){
        User1 user1=new User1();
        user1.setName("lisi");
        user1.setAge(24);
        return user1;
    }
}

测试:

    @Test
    public void test5(){
        AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext(TestConfiguration.class);
        User user = applicationContext.getBean(User.class);
        System.out.println(user);
        User1 user1 = applicationContext.getBean(User1.class);
        System.out.println(user1);
    }

得到打印结果:User没有获取到id属性

2020-01-22 15:21:36.079  INFO 9504 --- [           main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@13dab28: startup date [Wed Jan 22 15:21:36 CST 2020]; root of context hierarchy
User{id=\'null\', name=\'zhangsan\', age=23}
User1{id=\'user1\', name=\'lisi\', age=24}
2020-01-22 15:21:36.107  INFO 9504 --- [       Thread-2] o.s.w.c.s.GenericWebApplicationContext   : Closing org.springframework.web.context.support.GenericWebApplicationContext@1485fda: startup date [Wed Jan 22 15:21:33 CST 2020]; root of context hierarchy

以上是关于spring-beans中Aware相关接口的源码解析说明的主要内容,如果未能解决你的问题,请参考以下文章

SPRING07_源码之核心组件接口Aware

spring中aware接口的

spring源码分析:Aware接口让你的bean对容器直接操作

spring:spring中Aware接口的使用

Spring - BeanFactoryAware扩展接口

Spring - BeanFactoryAware扩展接口