Spring的Aware接口之ApplicationContextAware分析

2,080 阅读4分钟

在工作中,我们可能会使用到像下面这样的代码,用于从spring容器中获取我们想要的bean,那么,为什么这样就可以从spring容器中获的到呢?这篇文章就沿着主线梳理一下。

为了视线清晰,本篇在贴源码时时省略许多不相关的代码

@Component
public class ApplicationContextHolder implements ApplicationContextAware {
    private static ApplicationContext applicationContext;

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ApplicationContextHolder.applicationContext = applicationContext;
    }

    /**
     * 获取spring的bean
     */
    public static <T> T getBean(Class<T> requiredType) {
        return applicationContext.getBean(requiredType);
    }

    /**
     * 获取spring的bean
     */
    public static <T> T getBean(String beanName, Class<T> requiredType) {
        return applicationContext.getBean(beanName, requiredType);
    }

    /**
     * 获取spring的bean
     */
    public static Object getBean(String beanName) {
        return applicationContext.getBean(beanName);
    }
}
public interface ApplicationContextAware extends Aware {

	/**
	 * Set the ApplicationContext that this object runs in.
	 * Normally this call will be used to initialize the object.
	 * <p>Invoked after population of normal bean properties but before an init callback such
	 * as {@link org.springframework.beans.factory.InitializingBean#afterPropertiesSet()}
	 * or a custom init-method. Invoked after {@link ResourceLoaderAware#setResourceLoader},
	 * {@link ApplicationEventPublisherAware#setApplicationEventPublisher} and
	 * {@link MessageSourceAware}, if applicable.
	 * @param applicationContext the ApplicationContext object to be used by this object
	 * @throws ApplicationContextException in case of context initialization errors
	 * @throws BeansException if thrown by application context methods
	 * @see org.springframework.beans.factory.BeanInitializationException
	 */
	void setApplicationContext(ApplicationContext applicationContext) throws BeansException;

}

ApplicationContextAware继承了Aware这个顶级接口,而Aware这个接口里面其实啥也没有,就是起着一个标识的作用。ApplicationContextAware中只有一个方法,正如方法注释所言,在对象运行时设置ApplicationContext,通常被用来初始化对象。

下面这个方法是spring在容器准备阶段执行的,今天,我们也从这里开始梳理。

AbstractApplicationContext#refresh

	@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
		
			// 省略部分代码
	
			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);

			try {
				// 省略部分代码

				// Instantiate all remaining (non-lazy-init) singletons.
				finishBeanFactoryInitialization(beanFactory);

				//  省略部分代码

			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// 省略部分代码
				// Propagate exception to caller.
				throw ex;
			}

			finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
			}
		}
	}

首先沿着

prepareBeanFactory(beanFactory);

代码进去

AbstractApplicationContext#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()));

		// Configure the bean factory with context callbacks.
		beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

		// 省略部分代码
	}

这段代码里,添加了一个后置处理器ApplicationContextAwareProcessor,这个很关键,后面会提到。

new ApplicationContextAwareProcessor(this)

	public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
		this.applicationContext = applicationContext;
		this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
	}

通过构造方法,给ApplicationContextAwareProcessor这个后置处理器的applicationContext进行赋值,通过ConfigurableApplicationContext的继承关系可以看到,ConfigurableApplicationContext继承了ApplicationContext,也属于bean工厂。

AnnotationAwareAspectJAutoProxyCreator.png

然后回到开头的代码,这次沿着

finishBeanFactoryInitialization(beanFactory);

这块代码进入,这个方法看名字就知道是创建实例的。我们自己定义的ApplicationContextHolder交给了spring去管理,自然也会被创建。

AbstractAutowireCapableBeanFactory#doCreateBean

	protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
			throws BeanCreationException {

		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
		Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
		mbd.resolvedTargetType = beanType;

		// 省略部分代码。。。

		// 省略部分代码。。。

		// 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);
			}
		}

		// 省略部分代码。。。
	
		return exposedObject;
	}

从这个方法里面可以看到,先是使用createBeanInstance(beanName, mbd, args)创建出了一个实例,然后通过 populateBean(beanName, mbd, instanceWrapper);填充属性,再然后通过initializeBean(beanName, exposedObject, mbd);执行初始化bean,这个也是我们此次要跟进的方法。

AbstractAutowireCapableBeanFactory#initializeBean

	protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged(new PrivilegedAction<Object>() {
				@Override
				public Object run() {
					invokeAwareMethods(beanName, bean);
					return null;
				}
			}, getAccessControlContext());
		}
		else {
			invokeAwareMethods(beanName, 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;
	}

这个方法里面就是执行后置处理器的postProcessBeforeInitialization方法,初始化方法,和后置处理器的postProcessAfterInitialization方法。

	public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
			throws BeansException {

		Object result = existingBean;
		for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
			result = beanProcessor.postProcessBeforeInitialization(result, beanName);
			if (result == null) {
				return result;
			}
		}
		return result;
	}

其中就有我们开头上面提到的后置处理器ApplicationContextAwareProcessor

ApplicationContextAwareProcessor#postProcessBeforeInitialization

	@Override
	public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
		AccessControlContext acc = null;

		// 省略部分代码。。。

		if (acc != null) {
			// 省略部分代码。。。	
		}
		else {
			invokeAwareInterfaces(bean);
		}

		return bean;
	}

ApplicationContextAwareProcessor#invokeAwareInterfaces

	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);
			}
			if (bean instanceof ApplicationContextAware) {
				((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
			}
		}
	}

由于ApplicationContextHolder实现了ApplicationContextAware接口,所以最后一行代码肯定会执行,也就是说会执行ApplicationContextHolder的setApplicationContext方法,这里的this就是ApplicationContextAwareProcessor,它的applicationContext属性值就是上面提到的,通过它自己的构造方法完成对applicationContext属性的赋值的。而我们ApplicationContextHolder中的setApplicationContext就是把这个applicationContext赋值给了我们自己的一个属性,所以,我们就可以通过ApplicationContextHolder来从spring的容器中获取指定的bean了。

spring中还有很多像ApplicationContextAware这样的接口,感兴趣的可以研究研究~~~