1. spring bean生命周期二 - Aware接口

通过前面的学习,知道了spring bean的整个生命周期中调用的所有接口方法,也留下了几个需要解答的问题,现在我们先来看第一个问题:

生命周期的前10个调用方法,都是以Aware结尾的接口方法,各个XXXAware接口作用是什么?对开发者来说有没有用?

1.1. Aware单词释义

aware 英 [ə'weə]

adj. 意识到的;知道的;有…方面知识的;懂世故的

只看此英文单词,实在是想不出来spring中以Aware为后缀的接口的作用究竟是什么,下面我们看一下接口定义和描述;

1.2. 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.
 *
 * <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 BeanPostProcessor}.
 * Refer to {@link org.springframework.context.support.ApplicationContextAwareProcessor}
 * and {@link org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory}
 * for examples of processing {@code *Aware} interface callbacks.
 *
 * @author Chris Beams
 * @since 3.1
 */
public interface Aware {

}

从源码可以看出来:

  1. Aware是一个用来标记的顶层设计接口,不包括任务功能方法;实际的方法签名由它的子类来声明,一般来说,是只带一个参数且返回void的方法;
  2. Aware标记一个bean有资格让spring特定容器对象通过回调方法进行通知;

在使用spring时,我们把所有的bean交给spring容器进行管理,一般来讲,所有的bean专注于业务逻辑,它们不关心spring容器,也不知道自己在spring中是如何被管理的,在spring工厂中的代号是什么,换句话说,bean对于spring是无感知的。

spring提供了一系列的Aware接口作为hook,在不同的阶段调用不同的接口方法来通知一个bean,使bean可以对spring有所感知。

1.3. BeanNameAware

bean获取在BeanFactory中配置的名称(xml中的id或name),即一个实现了BeanNameAware接口的bean,可以获取其在工厂中的名称。

1.4. BeanFactoryAware

让bean对配置其BeanFactory有感知,即一个实现了BeanFactoryAware接口的bean,可以获取到配置它的BeanFactory实例。

其它的Aware类似,都是使一个bean对spring的某一方面有所感知,在特殊情况下,可以有用,但缺点也比较明显,就是对spring api耦合比较高,一般情况下,不建议使用。

1.5. AwareDemo

BeanNameAwareSamplesBean

/**
 * {@link BeanNameAware#setBeanName(String)}: 获取此bean在容器中的名称
 * {@link BeanClassLoaderAware#setBeanClassLoader(ClassLoader)}: 获取此bean在spring中初始化使用的classloader
 * {@link BeanFactoryAware#setBeanFactory(BeanFactory)}: 获取此bean在spring中所处的{@link BeanFactory}
 * {@link ApplicationContextAware#setApplicationContext(ApplicationContext)}:获取此bean的容器
 */
public class AwareSamplesBean implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, ApplicationContextAware {

    public static final Logger LOGGER = LoggerFactory.getLogger(BeanNameAwareSamplesBean.class);

    private String beanName;

    private ClassLoader beanClassLoader;

    private BeanFactory beanFactory;

    private ApplicationContext applicationContext;

    @Override
    public void setBeanName(String name) {
        LOGGER.info("获取bean在spring容器中的名称:{}", name);
        this.beanName = name;
    }

    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        LOGGER.info("获取beanClassLoader: {}", classLoader);
        this.beanClassLoader = classLoader;
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        LOGGER.info("获取beanFactory : {}", beanFactory);
        this.beanFactory = beanFactory;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        LOGGER.info("获取 applicationContext: {}", applicationContext);
        this.applicationContext = applicationContext;
    }
}

xml配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean class="samples.spring.step2.beans.MyBeanPostProcesser"/>

    <bean id="awareSamplesBean" class="samples.spring.step2.beans.AwareSamplesBean"/>
</beans>

main函数:

public static void main(String[] args) {
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:step2/step2.xml");
    LOGGER.info("==============classpathxmlapplicationcontext create completed.");
    context.registerShutdownHook();
}

结果

2017-04-12 13:46:35.912 [main] INFO  org.springframework.context.support.ClassPathXmlApplicationContext [581] - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@6aaa5eb0: startup date [Wed Apr 12 13:46:35 CST 2017]; root of context hierarchy
2017-04-12 13:46:35.956 [main] INFO  org.springframework.beans.factory.xml.XmlBeanDefinitionReader [317] - Loading XML bean definitions from class path resource [step2/step2.xml]
2017-04-12 13:46:36.082 [main] INFO  samples.spring.step2.beans.AwareSamplesBean [33] - 获取bean在spring容器中的名称:awareSamplesBean
2017-04-12 13:46:36.084 [main] INFO  samples.spring.step2.beans.AwareSamplesBean [39] - 获取beanClassLoader: sun.misc.Launcher$AppClassLoader@4d7e1886
2017-04-12 13:46:36.084 [main] INFO  samples.spring.step2.beans.AwareSamplesBean [45] - 获取beanFactory : org.springframework.beans.factory.support.DefaultListableBeanFactory@75881071: defining beans [samples.spring.step2.beans.MyBeanPostProcesser#0,awareSamplesBean]; root of factory hierarchy
2017-04-12 13:46:36.085 [main] INFO  samples.spring.step2.beans.AwareSamplesBean [51] - 获取 applicationContext: org.springframework.context.support.ClassPathXmlApplicationContext@6aaa5eb0: startup date [Wed Apr 12 13:46:35 CST 2017]; root of context hierarchy
2017-04-12 13:46:36.085 [main] INFO  samples.spring.step2.beans.MyBeanPostProcesser [17] - ============beanname:awareSamplesBean postprocesser:MyBeanPostProcesser's method:postProcessBeforeInitialization invoked.
2017-04-12 13:46:36.085 [main] INFO  samples.spring.step2.beans.MyBeanPostProcesser [23] - ============beanname:awareSamplesBean postprocesser:MyBeanPostProcesser's method:postProcessAfterInitialization invoked.
2017-04-12 13:46:36.100 [main] INFO  samples.spring.step1.SpringAppStep1 [20] - ==============classpathxmlapplicationcontext create completed.
2017-04-12 13:46:36.101 [Thread-0] INFO  org.springframework.context.support.ClassPathXmlApplicationContext [982] - Closing org.springframework.context.support.ClassPathXmlApplicationContext@6aaa5eb0: startup date [Wed Apr 12 13:46:35 CST 2017]; root of context hierarchy

Process finished with exit code 0

可以看到,顺序确实是按照bean生命周期中的顺序进行调用的。

Copyright © wychuan.com 2017 all right reserved,powered by Gitbook该文件修订时间: 2018-01-09 08:05:07

results matching ""

    No results matching ""