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相关接口的源码解析说明的主要内容,如果未能解决你的问题,请参考以下文章