ApplicationContextAware详解

一、进入正题

Aware转义就是"主动的",顾名思义spring给咱们主动做了些事件。spring有很多以Aware结尾的类,有EnvironmentAware、ApplicationContextAware、MessageSourceAware等。

这里我次要讲一下ApplicationContextAware。

如下文援用,ApplicationContextAware的文档能够浏览 Spring Core Technologies 1.4.6 Method Injection 、Spring Core Technologies 1.6.2. ApplicationContextAware and BeanNameAware、办法注入

概括一下,就是:

在大多数应用程序场景中,容器中的大多数bean都是单例的。当一个单例bean须要与另一个单例bean合作,或者一个非单例bean须要与另一个非单例bean合作时,通常通过将一个bean定义为另一个bean的属性来解决依赖关系。当bean的生命周期不同时,就会呈现问题。假如单例bean A须要应用非单例(原型)bean B,可能是在A的每个办法调用上。容器只创立单例bean A一次,因而只有一次机会设置属性。容器不能在每次须要bean A时都向bean A提供一个新的bean B实例。

一个解决方案是放弃一些管制反转。您能够通过实现ApplicationContextAware接口,以及在bean A每次须要bean B实例时对容器进行getBean(“B”)调用,从而使bean A aware(主动获取到) 容器。

二、应用

@Service("gatewayService")public class GatewayServiceImpl implements IGatewayService,ApplicationContextAware {    Map<ServiceBeanEnum,IGatewayBo> chargeHandlerMap=new HashMap<ServiceBeanEnum,IGatewayBo>();    private ApplicationContext applicationContext;    @Override    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {        this.applicationContext=applicationContext;    }}

在咱们须要应用ApplicationContext的服务中实现ApplicationContextAware接口,系统启动时就能够主动给咱们的服务注入applicationContext对象,咱们就能够获取到ApplicationContext里的所有信息了。

三、原理剖析

咱们都晓得spring的入口办法就在AbstractApplicationContext的refresh()办法,咱们先去看看refresh().prepareBeanFactory()办法。

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {        // Tell the internal bean factory to use the context's class loader etc.        beanFactory.setBeanClassLoader(getClassLoader());        beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));        beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));        // 增加ApplicationContextAware的处理器        beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));        beanFactory.ignoreDependencyInterface(EnvironmentAware.class);        beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);        beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);        beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);        beanFactory.ignoreDependencyInterface(MessageSourceAware.class);        beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);                ...    }

也就是说,spring在启动的时候给咱们增加了ApplicationContextAwareProcessor这样一个processor,进去看看它的实现:

@Overridepublic Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {    AccessControlContext acc = null;    if (System.getSecurityManager() != null &&        (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||         bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||         bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {        acc = this.applicationContext.getBeanFactory().getAccessControlContext();    }    if (acc != null) {        AccessController.doPrivileged((PrivilegedAction)() -> {            //外围办法,调用aware接口办法            invokeAwareInterfaces(bean);            return null;        }, acc);    } else {        invokeAwareInterfaces(bean);    }    return bean;}//实现private void invokeAwareInterfaces(Object bean) {    if (bean instanceof Aware) {        if (bean instanceof EnvironmentAware) {            ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());        }        if (bean instanceof EmbeddedValueResolverAware) {            ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);        }        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);        }        //针对实现了ApplicationContextAware的接口,spring都将调用其setApplicationContext,将applicationContext注入到以后bean对象。        if (bean instanceof ApplicationContextAware) {            ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);        }    }}

那ApplicationContextAwareProcessor又是什么时候调用的呢?咱们接着往下看,原来refresh()办法中还有个beanFactory.preInstantiateSingletons()办法,外面有这样一段代码:

拿到所有的beanNames,而后顺次判断是否须要加载,如果是,则调用getBean(beanName)办法实例化进去。// Trigger initialization of all non-lazy singleton beans...    for (String beanName : beanNames) {        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);        if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {            if (isFactoryBean(beanName)) {                final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);                boolean isEagerInit;                if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {                    isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {                        @Override                        public Boolean run() {                            return ((SmartFactoryBean<?>) factory).isEagerInit();                        }                    }, getAccessControlContext());                }                else {                    isEagerInit = (factory instanceof SmartFactoryBean &&                                   ((SmartFactoryBean<?>) factory).isEagerInit());                }                if (isEagerInit) {                    getBean(beanName);                }            }            else {                getBean(beanName);            }        }    }

顺次查看getBean() ->doGetBean()->createBean()->doCreateBean()办法:

// Initialize the bean instance.Object exposedObject = bean;try {    populateBean(beanName, mbd, instanceWrapper);    if (exposedObject != null) {        exposedObject = initializeBean(beanName, exposedObject, mbd);    }} catch (Throwable ex) {    if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {        throw (BeanCreationException) ex;    } else {        throw new BeanCreationException(            mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);    }}

查看一下initializeBean办法:

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {    if (System.getSecurityManager() != null) {        AccessController.doPrivileged(() -> {            this.invokeAwareMethods(beanName, bean);            return null;        }, this.getAccessControlContext());    } else {        //调用setBeanName() 、setBeanClassLoaderAware、setBeanFactoryAware办法        this.invokeAwareMethods(beanName, bean);    }    Object wrappedBean = bean;    if (mbd == null || !mbd.isSynthetic()) {        wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);    }    try {        //调用afterPropertiesSet()办法        this.invokeInitMethods(beanName, wrappedBean, mbd);    } catch (Throwable var6) {        throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);    }    //这里才是ApplicationContextProcessor的postProcessAfterInitialization()执行入口:    if (mbd == null || !mbd.isSynthetic()) {        wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);    }    return wrappedBean;}

原来AbstractAutowireCapableBeanFactory中的inititalBean()办法就是BeanPostProcessor的调用处。然而像BeanNameAware、BeanFactoryAware不同,是通过initialBean()中的invokeAwareMethods间接调用实现的

四、样例

import org.springframework.beans.factory.BeanFactoryUtils;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;import java.util.Map;/** * 通过Spring上下文获取bean工具类 * * @author moon */public class SpringContextUtils implements ApplicationContextAware {    /**     * Spring利用上下文环境     */    private static ApplicationContext applicationContext;    @Override    public void setApplicationContext(ApplicationContext applicationContext) {        SpringContextUtils.initSpringContext(applicationContext);    }    public static ApplicationContext getApplicationContext() {        return applicationContext;    }    @SuppressWarnings("unchecked")    public static <T> T getBean(String name) {        return (T) applicationContext.getBean(name);    }    public static <T> T getBean(Class<T> clazz) {        return applicationContext.getBean(clazz);    }    public static boolean isSingleton(String name) {        return applicationContext.isSingleton(name);    }    /**     * 依据class对象返回IOC容器中其对象和其子类的对象。     * 未找到则返回空MAP。     * KEY为BEAN ID或者NAME,VALUE为BEAN实例     *     * @param type 须要找的bean类型的CLASS对象     * @return bean映射     */    public static <T> Map<String, T> getBeansByType(Class<T> type) {        return BeanFactoryUtils.beansOfTypeIncludingAncestors(SpringContextUtils.getApplicationContext(), type);    }    /**     * 初始化ApplicationContext     *     * @param applicationContext 上下文     */    public static void initSpringContext(ApplicationContext applicationContext) {        SpringContextUtils.applicationContext = applicationContext;    }    /**     * 获取业务线(业务线配置在配置文件中)     *     * @return 业务线     */    public static String getProjectBusinessLine() {        if (applicationContext == null) {            throw new RuntimeException("spring初始化失败");        }        return applicationContext.getEnvironment().getProperty("***.application.businessLine");    }    /**     * 获取项目名称(项目名称配置在配置文件中)     *     * @return 项目名称     */    public static String getProjectName() {        if (applicationContext == null) {            throw new RuntimeException("spring初始化失败");        }        return applicationContext.getEnvironment().getProperty("***.application.name");    }}