Spring源码解析系列文章是我最近在学习了一段Spring,SpringBoot和SpringMVC等一系列的源码后整理的文章。我会随着我对Spring的理解来进行相应的文章的整合和归纳。
我决定从提出一个问题开始。然后围绕着解决这个问题的方式来剖析源码。当我们把一个问题搞懂了的时候。里面的源码我们也就清楚了。事实上看源码不是目标。解决一些日常的困惑才是目标。
为什么被Spring管理的类。只要实现了Aware接口。Spring就会自动把对应的对象注入进来。这个bean如果想要使用直接使用就可以了。如下: Spring会自动把ApplicationContext注入到AwareTest这个bean里面。
public class AwareTest implements ApplicationContextAware {
public ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
public void checkAware(){
if(applicationContext != null){
System.out.println("ApplicationContext inject success");
}
}
}
1. 我们都知道在AbstractApplicationContext里面真正的启动ApplicationContext的函数是refresh()方法。具体的方法如下
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(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();
}
}
}
2. 可以看到有一个prepareBeanFactory的方法,我们再往里面看一下这个方法里面究竟有什么。可以发现给BeanFactory添加了一个BeanPostProcessor。名字是ApplicationContextAwareProcessor
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));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
... 多余的代码不贴出来了
}
3. BeanPostProcessor这个接口我们都很熟悉了。我们看一下这个里面PostProcessBeforeInitialization()函数。传入bean和beanName。最后是调用了invokeAwareInterfaces(bean)这个函数。如果bean 是aware类的子类。那么就调用bean的set方法将ApplicationContext塞到bean里面。然后业务代码在需要使用ApplicationContext的时候就可以直接使用了。因为已经被set进来了。
public 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
4. 我们再来看一下。Spring是什么时候调用了BeanPostProcessor的postProcessBeforeInitialization函数的。在AbstractAutowireCapableBeanFactory的initializeBean方法里面 , 在调用InvokeInitMethods的方法之前。先执行了applyBeanPost
ProcessorBeforeInitialization的方法。这个方法里面就是将所有的BeanPostProcessor的的postProcessBeforeInitialization()都执行一遍。包括之前创建的ApplicationContextAwareProcessor。于是ApplicationContextAwareProcessor这个时刻就将ApplicationContext注入到我们的Bean里面了。
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction
上面是跟着源码走了一遍。我看完之后的理解就是。Spring在整个设计上对于这种松耦合和可插拔真是做了非常多的工作。可以说Spring 本身的ioc的代码并不复杂。大量的代码工作都是为了方便开发者自己去拓展Spring的边界。让开发者可以更好的去控制和管理bean这个对象。Spring的代码建议多读几遍。虽然每一遍读起来都很痛苦。但是每一次读都会有新的感受。
这一篇对原理的解析也还不错。参考链接