Spring相关接口之Aware接口

aware的英文意思:意识到,察觉到,发觉,发现。

从英文翻译来看,aware做的事情应该是发现某一个东西。

接着来看Aware接口源码:

/**
 * 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. Actual method signature is
 * determined by individual subinterfaces, but should typically
 * consist of just one void-returning method that accepts a single
 * argument.
 */
public interface Aware {

}

注释的大致意思是:Aware是一个标记性的超接口(顶级接口),指示了一个Bean有资格通过回调方法的形式获取Spring容器底层组件。实际回调方法被定义在每一个子接口中,而且通常一个子接口只包含一个接口一个参数并且返回值为void的方法。

说白了:只要实现了Aware子接口的Bean都能获取到一个Spring底层组件。

那么Aware都有哪些子接口呢?

Aware子接口:

其中我们可能比较熟悉的有:BeanFactoryAware、EnvironmentAware、ResourceLoaderAware、ImportAware、BeanNameAware、ApplicationContextAware。

接着我们再来看看BeanNameAware接口的源码:

/**
 * Interface to be implemented by beans that want to be aware of their
 * bean name in a bean factory. Note that it is not usually recommended
 * that an object depend on its bean name, as this represents a potentially
 * brittle dependence on external configuration, as well as a possibly
 * unnecessary dependence on a Spring API.
 */
public interface BeanNameAware extends Aware {

   /**
    * Set the name of the bean in the bean factory that created this bean.
    * <p>Invoked after population of normal bean properties but before an
    * init callback such as {@link InitializingBean#afterPropertiesSet()}
    * or a custom init-method.
    */
   void setBeanName(String name);

}

BeanNameAware子接口的注释大概意思:实现该接口的Bean,可以获取到Bean的名称。

setBeanName方法的作用就是获取BeanName。

同理可得:

-- 实现BeanFactoryAware接口的Bean,可以获取到BeanFactory组件对象。

-- 实现EnvironmentAware接口的Bean,可以获取到Environment组件对象。

归纳可得:

-- 实现XXXAware接口的Bean,那么通过实现的setXXX方法就可以获取到XXX组件对象。

Aware是spring定义的一种标记性接口,仅仅只是代表一种功能,类似的接口还有我们熟悉的java官方的标记性接口Serializable,表示实现该接口的Bean表可以被序列化到本地,当然Serializable可不像Aware接口那么简单,底层还是有很高深的东西在的,有兴趣研究底层实现的小伙伴,可以参考:https://juejin.im/post/5d0c4bebf265da1bc23f7f1d

此外,Aware接口的使用在Spring实现AOP也有体现。

虽然通过以上的分析可以顺理成章的整理出Aware接口的作用,但是毛主席说过:实践是检验真理的唯一标准,所以上代码检验!!!

--基础环境的准备:导入spring的核心jar包(bean、core、context、expression)

建议通过Maven仓库引入jar包的坐标,只需引入context即可依赖导入另外三个,非常方便。

--编写业务层组件ComponentServiceImpl,并实现BeanFactory接口。

@Service
public class ComponentServiceImpl implements BeanFactoryAware {

    private BeanFactory beanFactory;

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }

    public void showBeanFactory() {
        System.out.println(beanFactory);
    }
}

--编写Spring配置类

@Configuration
@ComponentScan("org.cjw")
public class JavaConfig {

}

--单元测试

@Test
public void testShowBeanFactory() {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(JavaConfig.class);
    ComponentServiceImpl componentServiceImpl = (ComponentServiceImpl) context.getBean("componentServiceImpl");
    componentServiceImpl.showBeanFactory();
}

--测试结果

通过结果,可以再得出一个结论,我们真的只需实现XXXAware接口,在实现的setXXX方法中将组件信息保存起来,我们在其他的方法中就可以使用该信息了,支撑这一过程的是后置处理器BeanPostProcessor,BeanPostProcessor作用是在Bean的初始化方法执行前后做事情,

而初始化方法是在Bean创建之后,IOC容器创建完毕之前执行了,所以将setXXX方法通过后置处理器放置在初始化方法之前或者之后执行,那么用户获取到Bean之前就把组件信息保存到Bean中了,所以上诉哪个案例才能打印出BeanFactory对象。

PS:学过反射配合注解就可以模拟spring实现这一过程了。

艾欧尼亚,昂扬不灭,为了更美好的明天而战(#^.^#)
原文地址:https://www.cnblogs.com/lovelywcc/p/14784459.html