Spring的bean加载流程源码分析

经过上几张文章对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方法,并在方法中进行个性化的属性处理及设置。

  1. 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实例化和依赖注入过程。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值