如果你了解过 Spring Bean 的生命周期的相关内容的时候,你肯定会对 BeanNameAware 和BeanClassLoaderAware 这样的以 Aware 结尾的类,这样就是我们今天要提到的第一个内容,回调注入。

1. 回调函数

回调的开始,就是在 Spring 的 beans 组件下的 org.springframework.beans.factory.Aware 这个接口

  1. package org.springframework.beans.factory;
  2. public interface Aware {
  3. }

而实现了这个接口的子类是非常多的,例如下面几个常用的

接口名 用途
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 方法,从而能引入某些内容。