经过上几张文章对Spring大致流程的分析,这里开始对Spring源码进行探索解读:
ApplicationContext ac = new ClassPathXmlApplicationContext("application-context.xml");
点击进入ClassPathXmlApplicationContext内部:
//这里是ClassPathXmlApplicationContext的构造函数
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
//上面this调用的方法如下:
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);//调用父级的构造方法
//设置要读取的配置文件的路径
setConfigLocations(configLocations);
if (refresh) {//是否自动刷新上下文
refresh();//调用刷新上下文方法
}
}
//这里调用抽象类AbstractRefreshableConfigApplicationContext的setConfigLocations()方法
//这个方法的作用:解析指定的数组路径,如果数组中包含特殊符号,如${var},那么在resolvePath方法中会搜寻匹配的系统变量并替换
public void setConfigLocations(@Nullable String... locations) {
if (locations != null) {
Assert.noNullElements(locations, "Config locations must not be null");
this.configLocations = new String[locations.length];
for (int i = 0; i < locations.length; i++) {
//解析指定路径
this.configLocations[i] = resolvePath(locations[i]).trim();
}
}
else {
this.configLocations = null;
}
}
AbstractApplicationContext的refresh():
refresh函数中包含了几乎ApplicationContext中提供的全部功能
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
//1.调用容器准备刷新的方法,获取容器的当前时间,同时给容器设置同步标识
prepareRefresh();
//2.创建新的bean工厂,加载配置;
//告诉子类启动refreshBeanFactory()方法,Bean定义资源文件的载入从子类的refreshBeanFactory()方法启动
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//3.为BeanFactory配置容器特性,例如类加载器、事件处理器等
prepareBeanFactory(beanFactory);
try {
//4.允许在子类上下文对bean工厂进行后处理(为容器的某些子类指定特殊的BeanPost事件处理器)
postProcessBeanFactory(beanFactory);
//5.激活各种BeanFactory处理器;
invokeBeanFactoryPostProcessors(beanFactory);
//6.注册拦截bean创建的bean处理器,这里只是注册,真正的调用是在getBean时候
registerBeanPostProcessors(beanFactory);
//7.初始化信息源,和国际化相关.
initMessageSource();
//8.初始化此上下文的事件多播器
initApplicationEventMulticaster();
//9.模板方法,它可以被覆盖以添加特定于上下文的刷新工作。
onRefresh();
//10.注册监听器
registerListeners();
//11.实例化所有剩余的(非lazy-init)单例,实例化对象
finishBeanFactoryInitialization(beanFactory);
//12.初始化容器的生命周期事件处理器,并发布容器的生命周期事件
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
//销毁已经创建的单例,以避免占用资源
destroyBeans();
//重置“活跃”的标记
cancelRefresh(ex);
//将异常抛给调用者
throw ex;
}
finally {
//在Spring的核心中重置公共自省缓存,因为我们可能再也不需要单例bean的元数据了
resetCommonCaches();
}
}
}
上面的代码实现的功能:
1.Spring容器的创建和配置文件的加载、解析功能;
2.初始化Spring容器相关配置;
3.实例化所有剩余的(非lazy-init)单例;
这里具体来看一下这些方法的作用:
1.prepareRefresh()方法:准备刷新上下文环境
protected void prepareRefresh() {
//获取当前时间
this.startupDate = System.currentTimeMillis();
//将容器切换到活跃
this.closed.set(false);
this.active.set(true);
if (logger.isInfoEnabled()) {
logger.info("Refreshing " + this);
}
//初始化上下文环境中的任何占位符属性源(留给子类实现)
initPropertySources();
//验证需要的属性文件是否都已经放入环境中
getEnvironment().validateRequiredProperties();
//存储预刷新状态的ApplicationListeners
//若预刷新状态的ApplicationListeners为空,则将ApplicationListeners放入到预刷新状态的ApplicationListeners中
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
else {
//将ApplicationListeners重置为预刷新状态
//若预刷新状态的ApplicationListeners不为空,则将applicationListeners清空,将预刷新状态的ApplicationListeners(earlyApplicationListeners)放入到ApplicationListeners中
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
//创建ApplicationEvents集合,一旦多播器可用,将被发布
this.earlyApplicationEvents = new LinkedHashSet<>();
}
initPropertySources()这个方法点开发现是空的,这里可以理解为Spring框架为用户提供的扩展点,这里留一个空方法留给用户实现,给用户最大扩展Spring的能力。用户可以根据自身的需要重写initPropertySources方法,并在方法中进行个性化的属性处理及设置。
- obtainFreshBeanFactory();bean工厂的创建和xml等配置文件的加载。
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
//这里使用了委派设计模式,父类定义了抽象的refreshBeanFactory()方法,
// 具体实现调用子类容器的refreshBeanFactory()方法
//创建新的工厂,如果之前存在就:destroyBeans()调用方法销毁;closeBeanFactory();调用方法关闭
//这里使用AbstractRefreshableApplicationContext这个实现类
//初始化BeanFactory,并进行XML文件读取,并将得到的BeanFactory记录在当前实体属性中
refreshBeanFactory();
//获取上一步中新创建的工厂
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
//这里才创建bean工厂:AbstractRefreshableApplicationContext的refreshBeanFactory()方法
@Override
protected final void refreshBeanFactory() throws BeansException {
//判断beanFactory是否存在
if (hasBeanFactory()) {
// 若存在:
// 销毁beanFactory
destroyBeans();
// 关闭beanFactory
closeBeanFactory();
}
try {
//这里创建 DefaultListableBeanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
//设置序列化化id,若有需要就可根据这个id反序列化到这个beanFactory对象
beanFactory.setSerializationId(getId());
//对IOC容器进行定制化,如设置启动参数
customizeBeanFactory(beanFactory);
//调用载入Bean定义的方法,主要这里又使用了一个委派模式,
//在当前类中只定义了抽象的loadBeanDefinitions方法,具体的实现调用子类容器
//初始化docmentReader,并实现对xml的读取和解析
loadBeanDefinitions(beanFactory);//加载xml等配置文件
//设置此上下文的Bean工厂
this.beanFactory = beanFactory;
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
//创建一个新的DefaultListableBeanFactory;getInternalParentBeanFactory()该方法是获取父级工厂
protected DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}
//调用的为AbstractApplicationContext的getInternalParentBeanFactory()方法获取父级工厂,
//在AbstractApplicationContext抽象类中
protected BeanFactory getInternalParentBeanFactory() {
return (getParent() instanceof ConfigurableApplicationContext ?
((ConfigurableApplicationContext) getParent()).getBeanFactory() : getParent());
}
//此上下文的父上下文,getParent()获取的就是这个属性,获取父级的上下文
@Nullable
private ApplicationContext parent;
//来看一下,什么时候设置了父级工厂,这里就要回到ClassPathXmlApplicationContext的构造函数中了,
//其中有super(parent);这段代码,作用:调用父级的构造方法,并传递一个参数ApplicationContext parent.
//点进super(parent)
public AbstractXmlApplicationContext(@Nullable ApplicationContext parent) {
super(parent);
}
//再次点进super(parent)
public AbstractRefreshableConfigApplicationContext(@Nullable ApplicationContext parent) {
super(parent);
}
//再次点进super(parent)
public AbstractRefreshableApplicationContext(@Nullable ApplicationContext parent) {
super(parent);
}
//在AbstractApplicationContext抽象类中看到了setParent(parent);设置父级上下文的方法
public AbstractApplicationContext(@Nullable ApplicationContext parent) {
this();
setParent(parent);
}
//setParent方法如下
public void setParent(@Nullable ApplicationContext parent) {
this.parent = parent;//这里的parent: ApplicationContext parent;
if (parent != null) {
Environment parentEnvironment = parent.getEnvironment();
if (parentEnvironment instanceof ConfigurableEnvironment) {
getEnvironment().merge((ConfigurableEnvironment) parentEnvironment);
}
}
}
//经过上面的源码查看可以看出在实例化ClassPathXmlApplicationContext时设置了父级上下文对象,看参数可知,
//this(new String[] {configLocation}, true, null),此时设置的父级上下文对象为空,即:ApplicationContext parent = null;
//所以这里的getInternalParentBeanFactory方法获取的父级工厂就为null.所以这里创建的DefaultListableBeanFactory传递的父级工厂为null。
//配置上一步创建的beanFactory
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
//如果allowBeanDefinitionOverriding不为空,设置给beanFactory对象相应属性
if (this.allowBeanDefinitionOverriding != null) {
//是否允许覆盖同名称的不同定义的对象
beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
//如果allowCircularReferences不为空,设置给beanFactory对象相应属性
if (this.allowCircularReferences != null) {
//是否允许bean之间存在循环依赖
beanFactory.setAllowCircularReferences(this.allowCircularReferences);
}
}
//配置XmlBeanDefinitionReader,读取配置文件
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
//为指定beanFactory创建XmlBeanDefinitionReader
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
//为beanDefinitionReader进行环境变量设置
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
//对beanDefinitionReader进行设置,可以覆盖
initBeanDefinitionReader(beanDefinitionReader);
//进行配置文件读取
loadBeanDefinitions(beanDefinitionReader);
}
//XmlBeanDefinitionReader中已经将之前初始化的DefaultListableBeanFactory注册进去了,所以XmlBeanDefinitionReader所读取的
//BeanDefinitionHolder都会注册到DefaultListableBeanFactory中,也就是经过此步骤,
//类型DefaultListableBeanFactory的变量beanFactory已经包含了所有解析好的配置.
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
Resource[] configResources = getConfigResources();
if (configResources != null) {
reader.loadBeanDefinitions(configResources);
}
String[] configLocations = getConfigLocations();
if (configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
}
2.这个方法开始创建(非懒加载)对象,finishBeanFactoryInitialization();
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 初始化此上下文的转换服务。
//这是Spring3以后新加的代码,为容器指定一个转换服务(ConversionService)
//在对某些Bean属性进行转换时使用
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// 如果没有bean后处理程序,则注册一个默认的嵌入式值解析器
// (例如PropertyPlaceholderConfigurer bean)在此之前注册: 此时,主要用于解析注释属性值。
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// 尽早初始化LoadTimeWeaverAware bean,以允许尽早注册它们的转换器。
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
//为了类型匹配,停止使用临时的类加载器
beanFactory.setTempClassLoader(null);
//缓存容器中所有注册的BeanDefinition元数据,以防被修改
beanFactory.freezeConfiguration();
// 实例化所有剩余的(非lazy-init)单例。
beanFactory.preInstantiateSingletons();
}
//这里调用了ConfigurableListableBeanFactory接口的preInstantiateSingletons()方法,
//其实现类为DefaultListableBeanFactory(Spring初始化创建的bean工厂),所以说这个方法是在Spring的bean工厂中执行的,该bean工厂在
//经过上面XmlBeanDefinitionReader读取配置信息,已经包含了所有解析好的配置(比如在xml中配置bean信息).
public void preInstantiateSingletons() throws BeansException {
if (logger.isDebugEnabled()) {
logger.debug("Pre-instantiating singletons in " + this);
}
//从bean工厂中取出,按注册顺序排列的bean定义名称集合
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// 触发所有非惰性单例bean的初始化…
for (String beanName : beanNames) {
// 根据beanName获取对应的RootBeanDefinition定义信息
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 判断bean定义信息是否为抽象类,是否单例,是否为懒加载的
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
//判断当前类是否为工厂Bean,//如果指定名称的bean是创建容器的Bean
if (isFactoryBean(beanName)) {
//FACTORY_BEAN_PREFIX=”&”,当Bean名称前面加”&”符号时,
//获取的是产生容器对象本身,而不是容器产生的Bean.
//调用getBean方法,触发容器对Bean实例化和依赖注入过程
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
FactoryBean<?> factory = (FactoryBean<?>) bean;
//标识是否需要预实例化
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(
(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
//调用getBean方法,触发容器对Bean实例化和依赖注入过程
getBean(beanName);
}
}
}
else {
//调用getBean方法,触发容器对Bean实例化和依赖注入过程
getBean(beanName);
}
}
}
// 触发所有适用bean的初始化后回调
for (String beanName : beanNames) {
//从缓存中获取对应的bean
Object singletonInstance = getSingleton(beanName);
//判断创建的对象是否实现SmartInitializingSingleton接口
if (singletonInstance instanceof SmartInitializingSingleton) {
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
// 如果存在实现SmartInitializingSingleton接口的bean,
// 那么Spring还会调用到该bean的afterSingletonsInstantiated()方法
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
该方法实现了从bean工厂中获取注册的beanName信息,并依次遍历,若为单例对象则调用getBean方法,触发容器对Bean实例化和依赖注入过程。