博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
spring源码:Aware接口
阅读量:5052 次
发布时间:2019-06-12

本文共 6422 字,大约阅读时间需要 21 分钟。

一、spring容器中的aware接口介绍

  Spring中提供了各种Aware接口,比较常见的如BeanFactoryAware,BeanNameAware,ApplicationContextAware,BeanClassLoaderAware等,方便从上下文中获取当前的运行环境。我们先从使用的角度来说明aware接口的使用方式,举例如我们想得到当前的BeanFactory,我们可以让我们的实现类继承BeanFactoryAware接口,然后通过接口注入的方式得到当前容器中的BeanFactory:

public class Fruit implements BeanFactoryAware {    private BeanFactory beanFactory;     @Override    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {        this.beanFactory = beanFactory;    }}

我们的Fruit类实现了aware接口,如果我们直接在应用中new一个Fruit的对象,当然是拿不到beanFactory变量的,我们必须在spring的配置文件中声明我们的fruit对象才行,也就是说fruit对象必须交给容器进行管理,容器帮你把各种aware接口中想要注入的对象设置到bean中。具体看容器管理aware接口的代码实现,代码在AbstractAutowireCapableBeanFactory的initializeBean方法中:

protected Object initializeBean(String beanName, Object bean, RootBeanDefinition mbd) {    // 判断对象实现的接口类型,处理特定的三种接口类型:BeanNameAware、BeanClassLoaderAware和BeanFactoryAware。    if (bean instanceof BeanNameAware) {        ((BeanNameAware) bean).setBeanName(beanName);    }     if (bean instanceof BeanClassLoaderAware) {        ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());    }     if (bean instanceof BeanFactoryAware) {        ((BeanFactoryAware) bean).setBeanFactory(this);    }    // 开始Bean初始化前处理、初始化、初始化后处理    Object wrappedBean = bean;    if (mbd == null || !mbd.isSynthetic()) {        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);    }     try {        invokeInitMethods(beanName, wrappedBean, mbd);    }    catch (Throwable ex) {        throw new BeanCreationException(                (mbd != null ? mbd.getResourceDescription() : null),                beanName, "Invocation of init method failed", ex);    }     if (mbd == null || !mbd.isSynthetic()) {        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);    }    return wrappedBean;}

可以看出来,aware接口的各种处理是在属性设置完成之后、bean初始化之前完成的。显然的,如果我们直接new出来一个bean,这些框架性的特性是没有使用到的。除了BeanFactoryAware、BeanNameAware、BeanClassLoaderAware之外的那些aware接口,比如ApplicationContextAware,再比如Webx中的自定义aware接口,它们又是怎么做到接口注入的呢?原来在应用中创建上下文容器时会注册一个BeanPostProcessor------ApplicationContextAwareProcessor,在这个类里面进行了context的注入,这样我们就能能够拿到bean中的context对象:

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {    if (bean instanceof ResourceLoaderAware) {        ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);    }    if (bean instanceof ApplicationEventPublisherAware) {        ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);    }    if (bean instanceof MessageSourceAware) {        ((MessageSourceAware) bean).setMessageSource(this.applicationContext);    }    if (bean instanceof ApplicationContextAware) {        ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);    }    return bean;}

那么容器是在什么时候把ApplicationContextAwareProcessor的对象注册到context的BeanPostProcessor列表中的呢,奥秘在org.springframework.context.support.AbstractApplicationContext.prepareBeanFactory(ConfigurableListableBeanFactory)方法中:

// Tell the internal bean factory to use the context's class loader.beanFactory.setBeanClassLoader(getClassLoader()); // Populate the bean factory with context-specific resource editors.beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this)); // Configure the bean factory with context callbacks.beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); //在这里注册了我们想要的BeanPostProcessorbeanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);beanFactory.ignoreDependencyInterface(MessageSourceAware.class);beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

二、了解webx中实现的aware接口

  我们了解了aware的实现原理,我们就可以自己来实现自己的aware接口了。Webx就是这么做的(webx本身作为一个容器,本身注册了各类aware接口的BeanPostProcessor),比如我们想要感知到当前环境是否是生产模式,我们只需要实现ProductionModeAware接口就能够获得生产模式的值了。我们使用aware接口感觉很神奇很简便,原因是很多工作框架已经帮我们做了。webx中使用ProductionModeAwarePostProcessor这个BeanPostProcessor来进行生产模式的注入。在postProcessBeforeInitialization方法中:

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {    if (bean instanceof ProductionModeAware) {        ((ProductionModeAware) bean).setProductionMode(configuration.isProductionMode());    }     return bean;}

所以任何实现了ProductionModeAware接口的类,在webx容器中都能够获得生产模式的取值。

三、自定义aware接口实现

  了解了个中原理,那么自定义aware接口实现起来并不复杂。我们只需要2步操作:1.实现我们aware接口的postprocessor,并在容器中注册;2.bean实体类集成我们自定义的aware接口并实现。代码如下:Aware接口比较简单,就做一件事情,把Apple对象注入。

public interface AppleAware {    void setApple(Apple a);}

我们的BeanPostProcessor会检查是否是AppleAware接口,因为注册到容器的BeanPostProcessor会对每一个bean都做一次扫描:

public class AppleAwarePostProcessor implements BeanPostProcessor {     private Apple a;     public AppleAwarePostProcessor(Apple a) {        this.a = a;    }     /* (non-Javadoc)     * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String)     */    @Override    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {        if(bean instanceof AppleAware) {            ((AppleAware) bean).setApple(a);        }        return bean;    }     /* (non-Javadoc)     * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang.Object, java.lang.String)     */    @Override    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {        // TODO Auto-generated method stub        return bean;    } }

实体类Market实现了AppleAware接口,能够得到Apple对象的注入:

public class Market implements AppleAware {     private Apple a;     @Override    public void setApple(Apple a) {         this.a = a;    }     public String getName() {        return a.getName();    } }

最后是我们的测试类,一定要把我们的BeanPostProcessor加入到当前容器中,这一点非常重要:

public class TestAware {    public static void main(String args[]) {        ConfigurableBeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));        BeanPostProcessor bpp = new AppleAwarePostProcessor((Apple)beanFactory.getBean("apple"));    // 工厂对象中加入我们自定义的BeanPostProcessor        beanFactory.addBeanPostProcessor(bpp);        Market market = (Market) beanFactory.getBean("market");        System.out.println(market.getName());    }}

四、

转载于:https://www.cnblogs.com/RunForLove/p/5828916.html

你可能感兴趣的文章
WPF星空效果
查看>>
WPF Layout 系统概述——Arrange
查看>>
PIGOSS
查看>>
几款Http小服务器
查看>>
iOS 数组排序
查看>>
第三节
查看>>
PHP结合MYSQL记录结果分页呈现(比较实用)
查看>>
Mysql支持的数据类型
查看>>
openSuse beginner
查看>>
Codeforces 620E(线段树+dfs序+状态压缩)
查看>>
Windows7中双击py文件运行程序
查看>>
Market entry case
查看>>
bzoj1230 开关灯 线段树
查看>>
LinearLayout
查看>>
学习python:day1
查看>>
css3动画属性
查看>>
第九次团队作业-测试报告与用户使用手册
查看>>
Equal Sides Of An Array
查看>>
CentOS笔记-用户和用户组管理
查看>>
Mongodb 基本命令
查看>>