如果你了解过 Spring Bean 的生命周期的相关内容的时候,你肯定会对 BeanNameAware 和BeanClassLoaderAware 这样的以 Aware 结尾的类,这样就是我们今天要提到的第一个内容,回调注入。
1. 回调函数
回调的开始,就是在 Spring 的 beans 组件下的 org.springframework.beans.factory.Aware 这个接口
package org.springframework.beans.factory;
public interface Aware {
}
而实现了这个接口的子类是非常多的,例如下面几个常用的
接口名 | 用途 |
---|---|
BeanFactoryAware | 回调注入 BeanFactory |
ApplicationContextAware | 回调注入 ApplicationContext(与前面的不完全一样) |
EnvironmentAware | 回调注入 Environment |
ApplicationEventPublisherAware | 回调注入事件发布器 |
ResourceLoaderAware | 回调注入资源加载器(XML 驱动可用) |
BeanClassLoaderAware | 回调注入加载当前 Bean 的 ClassLoader |
BeanNameAware | 回调注入当前 Bean 的名称 |
不过就以目前 5.x.x 的版本来看,@Autowired 这个注解其实已经解决了大部分问题,上面这些 Aware 基本都不需要使用,只是最后两个 BeanNameAware 和 BeanClassLoaderAware 根据不同的 bean 有一定的区别,所以还需要 Aware 帮忙注入。
1.1 ApplicationContextAware
TestAwareBean 这个类实现了 ApplicationContextAware 接口,重写了对应的 set 方法,其实做的事情就是将 ApplicationContext 注入进去了。为了证明是否注入成功,我在其中调用了一下 ApplicationContext 的 getBeanDefinitionNames 方法来测试,如果等会可以正常的输出则是成功了。
public class TestAwareBean implements ApplicationContextAware {
private ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context = applicationContext;
}
public void testPrintBeanName(){
Stream.of(context.getBeanDefinitionNames()).forEach(System.out::println);
}
}
然后把这个 TestAwareBean 类注入,这里选择了这种麻烦的方式,而不是直接注解扫描是为了后面的演示。
@Configuration
public class AwareConfiguration {
@Bean
public TestAwareBean test() {
return new TestAwareBean();
}
}
测试一下
public class Test {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(AwareConfiguration.class);
TestAwareBean bean = context.getBean(TestAwareBean.class);
bean.testPrintBeanName();
}
}
运行结果
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
awareConfiguration
test
1.2 BeanNameAware
这个 aware 有什么用处呢,如果在某些情况下,如果当前的 bean 需要依赖自己的 name,那么光靠 @Autowired 就不行了,我们就需要通过 BeanNameAware 来将当前 bean 的 name 注入进来。
这就非常简单了,我们继续在刚才的 TestAwareBean 类上添加实现的接口 BeanNameAware,然后需要重写对应的 name set 方法,代码如下
public class TestAwareBean implements ApplicationContextAware, BeanNameAware {
private ApplicationContext context;
private String currentBeanName;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context = applicationContext;
}
@Override
public void setBeanName(String s) {
this.currentBeanName = s;
}
public void testPrintBeanName(){
Stream.of(context.getBeanDefinitionNames()).forEach(System.out::println);
}
public String getCurrentBeanName() {
return currentBeanName;
}
}
测试一下
public class Test {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(AwareConfiguration.class);
TestAwareBean bean = context.getBean(TestAwareBean.class);
bean.testPrintBeanName();
System.out.println(bean.getCurrentBeanName());
}
}
运行结果
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
awareConfiguration
test
test
补充:如果继续实现 NameBean 这个接口,那么它就会需要你实现它的 getBean 方法,就不需要自己自己创建 getBean 方法了。
后面不再继续补充了,例如 BeanClassLoaderAware ,其实都是一样的,实现后,都会通过实现对应的 set 方法,从而能引入某些内容。