详细解析SpringIOC加载过程

首先来一张图描述下spring的思想
在这里插入图片描述

Spring设计的初衷

Spring是为解决企业级应用开发的复杂性而设计,她可以做很多事。但归根到底支撑Spring的仅仅是少许的基本理念,而所有地这些的基本理念都能可以追溯到一个最根本的使命:简化开发。这是一个郑重的承诺,其实许多框架都声称在某些方面做了简化。
而Spring则立志于全方面的简化Java开发。对此,它主要采取了4个关键策略:
1,基于POJO的轻量级和最小侵入性编程;
2,通过依赖注入和面向接口松耦合;
3,基于切面和惯性进行声明式编程;
4,通过切面和模板减少样板式代码;
而他主要是通过:面向Bean、依赖注入以及面向切面这三种方式来达成的。

spring加载首先开始都是这样的代码

ApplicationContext context = new ClassPathXmlApplicationContext("classpath:application.xml");

意思是加载xml文件创建一个ApplicationContext 的Spring 容器。
那么就从new ClassPathXmlApplicationContext这个构造方法开始看吧。进入源码:

	public ClassPathXmlApplicationContext(
			String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
			throws BeansException {

		super(parent);
		setConfigLocations(configLocations);
		if (refresh) {
			refresh();
		}
	}

上面这个构造方法呢,其实就是new ClassPathXmlApplicationContext(“classpath:application.xml”) 真正开始的地方。
在这里插入图片描述
在这里插入图片描述
从上图可以看出来,ApplicationContext 其实就是一个BeanFactory,

  1. ApplicationContext 继承了ListableBeanFactory,这个ListableBeanFactory接口它可以获取多个bean,我们看BeanFactory接口的源码可以发现,BeanFactory的接口都是获取单个bean的
  2. 同时ApplicationContext 还继承了HierarchicalBeanFactory接口,这个接口可以在应用这起多个BeanFactory,然后将多个BeanFactory设置父子关系
  3. ApplicationContext 接口中的最后一个方法:AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException; 他的返回值是AutowireCapableBeanFactory,这个接口就是用来自动装配Bean的
    然后我们回到上面的 new ClassPathXmlApplicationContext(“classpath:application.xml”)构造方法。先看上面构造方法那个源码,setConfigLocations(configLocations);是根据提供的路径,处理成配置文件数组(以分号、逗号、空格、tab、换行符分割),然后就到了重点的refresh(); 这个refresh();方法可以用来重新初始化ApplicationContext ,下面贴出来这个方法的源码:
public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			//调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			//告诉子类启动refreshBeanFactory()方法,Bean定义资源文件的载入从
			//子类的refreshBeanFactory()方法启动
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			//为BeanFactory配置容器特性,例如类加载器、事件处理器等
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				//为容器的某些子类指定特殊的BeanPost事件处理器
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				//调用所有注册的BeanFactoryPostProcessor的Bean
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				//为BeanFactory注册BeanPost事件处理器.
				//BeanPostProcessor是Bean后置处理器,用于监听容器触发的事件
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				//初始化信息源,和国际化相关.
				initMessageSource();

				// Initialize event multicaster for this context.
				//初始化容器事件传播器.
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				//调用子类的某些特殊Bean初始化方法
				onRefresh();

				// Check for listener beans and register them.
				//为事件传播器注册事件监听器.
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				//初始化所有剩余的单例Bean
				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.
				//销毁已创建的Bean
				destroyBeans();

				// Reset 'active' flag.
				//取消refresh操作,重置容器的同步标识.
				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();
			}
		}
	}

可以看到这个方法里面调用了很多的方法,我们从开始说起:

  1. 首先是一个synchronized加锁,当然要加锁,不然你先调一次refresh()然后这次还没处理完又调一次,就会乱套了;
  2. 接着往下看prepareRefresh();这个方法是做准备工作的,记录容器的启动时间、标记“已启动”状态、处理配置文件中的占位符,可以点进去看看,这里就不多说了。
  3. 下一步ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();这个就很重要了,这一步是把配置文件解析成一个个Bean,并且注册到BeanFactory中,注意这里只是注册进去,并没有初始化。先继续往下看,等会展开这个方法详细解读
  4. 然后是prepareBeanFactory(beanFactory);这个方法的作用是:设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean,这里都是spring里面的特殊处理,然后继续往下看
  5. postProcessBeanFactory(beanFactory);方法是提供给子类的扩展点,到这里的时候,所有的 Bean 都加载、注册完成了,但是都还没有初始化,具体的子类可以在这步的时候添加一些特殊的
  6. BeanFactoryPostProcessor 的实现类,来完成一些其他的操作。
  7. 接下来是invokeBeanFactoryPostProcessors(beanFactory);这个方法是调用 BeanFactoryPostProcessor 各个实现类的 postProcessBeanFactory(factory) 方法;
  8. 然后是registerBeanPostProcessors(beanFactory);这个方法注册 BeanPostProcessor 的实现类,和上面的BeanFactoryPostProcessor 是有区别的,这个方法调用的其实是PostProcessorRegistrationDelegate类的registerBeanPostProcessors方法;这个类里面有个内部类BeanPostProcessorChecker,BeanPostProcessorChecker里面有两个方法postProcessBeforeInitialization和postProcessAfterInitialization,这两个方法分别在 Bean 初始化之前和初始化之后得到执行。然后回到refresh()方法中继续往下看
  9. initMessageSource();方法是初始化当前 ApplicationContext 的 MessageSource,国际化处理,继续往下
  10. initApplicationEventMulticaster();方法初始化当前 ApplicationContext 的事件广播器继续往下
  11. onRefresh();方法初始化一些特殊的 Bean(在初始化 singleton beans 之前);继续往下
  12. registerListeners();方法注册事件监听器,监听器需要实现 ApplicationListener 接口;继续往下
  13. 重点到了:finishBeanFactoryInitialization(beanFactory);初始化所有的 singleton beans(单例bean),懒加载(non-lazy-init)的除外,这个方法也是等会细说
  14. finishRefresh();方法是最后一步,广播事件,ApplicationContext 初始化完成

这就是整个refresh()方法调用的所有方法。这里只是简单描述一下,我们重点来看ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();和finishBeanFactoryInitialization(beanFactory);这两个方法。

先说ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); 这一步上面简单介绍过了,作用是把配置文件解析成一个个Bean,并且注册到BeanFactory中,点进去源码:

	protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		//这里使用了委派设计模式,父类定义了抽象的refreshBeanFactory()方法,具体实现调用子类容器的refreshBeanFactory()方法
		refreshBeanFactory();
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		if (logger.isDebugEnabled()) {
			logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
		}
		return beanFactory;
	}

这个方法中第一步refreshBeanFactory();方法的作用是关闭旧的 BeanFactory (如果有),创建新的 BeanFactory,加载 Bean 定义、注册 Bean 等,然后getBeanFactory();就是返回刚刚创建的 BeanFactory,我们进入refreshBeanFactory();方法,在AbstractRefreshableApplicationContext类中:

protected final void refreshBeanFactory() throws BeansException {
		//如果已经有容器,销毁容器中的bean,关闭容器
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
			//创建IOC容器
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			beanFactory.setSerializationId(getId());
			//对IOC容器进行定制化,如设置启动参数,开启注解的自动装配等
			customizeBeanFactory(beanFactory);
			//调用载入Bean定义的方法,主要这里又使用了一个委派模式,在当前类中只定义了抽象的loadBeanDefinitions方法,具体的实现调用子类容器
			loadBeanDefinitions(beanFactory);
			synchronized (this.beanFactoryMonitor) {
				this.beanFactory = beanFactory;
			}
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}
	}
  • 这个refreshBeanFactory()方法首先如果 ApplicationContext 中已经加载过 BeanFactory
    了,销毁所有 Bean,关闭 BeanFactory;这里指的是当前ApplicationContext 是否有 BeanFactory。
  • 然后createBeanFactory();初始化一个DefaultListableBeanFactory,这个DefaultListableBeanFactory是很重的一个类,为什么重要呢?可以看文章开头的BeanFactory继承图,DefaultListableBeanFactory是位于最下面的,他往上能走完BeanFactory继承图所有,所以他可以说是功能最大的BeanFactory。
    beanFactory.setSerializationId(getId());方法用于 BeanFactory 的序列化
  • customizeBeanFactory(beanFactory);方法设置 BeanFactory 的两个配置属性:是否允许 Bean 覆盖、是否允许循环引用,这个等会细说
  • loadBeanDefinitions(beanFactory);这个方法很重要:加载 Bean 到 BeanFactory 中,也是等会细说

下面看customizeBeanFactory(beanFactory);方法,这个方法作用:是否允许 Bean 覆盖、是否允许循环引用,这是什么意思呢?这就要说到BeanDefinition了,这里的 BeanDefinition 就是我们所说的 Spring 的 Bean,我们自己定义的各个 Bean 其实会转换成一个个 BeanDefinition 存在于 Spring 的 BeanFactory 中:

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {

   // 我们可以看到,默认只提供 sington 和 prototype 两种,
   // 很多读者可能知道还有 request, session, globalSession, application, websocket 这几种,
   // 不过,它们属于基于 web 的扩展。
   String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
   String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;

   // 比较不重要,直接跳过吧
   int ROLE_APPLICATION = 0;
   int ROLE_SUPPORT = 1;
   int ROLE_INFRASTRUCTURE = 2;

   // 设置父 Bean,这里涉及到 bean 继承,不是 java 继承。请参见附录的详细介绍
   // 一句话就是:继承父 Bean 的配置信息而已
   void setParentName(String parentName);

   // 获取父 Bean
   String getParentName();

   // 设置 Bean 的类名称,将来是要通过反射来生成实例的
   void setBeanClassName(String beanClassName);

   // 获取 Bean 的类名称
   String getBeanClassName();


   // 设置 bean 的 scope
   void setScope(String scope);

   String getScope();

   // 设置是否懒加载
   void setLazyInit(boolean lazyInit);

   boolean isLazyInit();

   // 设置该 Bean 依赖的所有的 Bean,注意,这里的依赖不是指属性依赖(如 @Autowire 标记的),
   // 是 depends-on="" 属性设置的值。
   void setDependsOn(String... dependsOn);

   // 返回该 Bean 的所有依赖
   String[] getDependsOn();

   // 设置该 Bean 是否可以注入到其他 Bean 中,只对根据类型注入有效,
   // 如果根据名称注入,即使这边设置了 false,也是可以的
   void setAutowireCandidate(boolean autowireCandidate);

   // 该 Bean 是否可以注入到其他 Bean 中
   boolean isAutowireCandidate();

   // 主要的。同一接口的多个实现,如果不指定名字的话,Spring 会优先选择设置 primary 为 true 的 bean
   void setPrimary(boolean primary);

   // 是否是 primary 的
   boolean isPrimary();

   // 如果该 Bean 采用工厂方法生成,指定工厂名称。对工厂不熟悉的读者,请参加附录
   // 一句话就是:有些实例不是用反射生成的,而是用工厂模式生成的
   void setFactoryBeanName(String factoryBeanName);
   // 获取工厂名称
   String getFactoryBeanName();
   // 指定工厂类中的 工厂方法名称
   void setFactoryMethodName(String factoryMethodName);
   // 获取工厂类中的 工厂方法名称
   String getFactoryMethodName();

   // 构造器参数
   ConstructorArgumentValues getConstructorArgumentValues();

   // Bean 中的属性值,后面给 bean 注入属性值的时候会说到
   MutablePropertyValues getPropertyValues();

   // 是否 singleton
   boolean isSingleton();

   // 是否 prototype
   boolean isPrototype();

   // 如果这个 Bean 是被设置为 abstract,那么不能实例化,
   // 常用于作为 父bean 用于继承,其实也很少用......
   boolean isAbstract();

   int getRole();
   String getDescription();
   String getResourceDescription();
   BeanDefinition getOriginatingBeanDefinition();
}

BeanDefinition 的覆盖问题就是在配置文件中定义 bean 时使用了相同的 id 或 name,默认情况下,allowBeanDefinitionOverriding 属性为 null,如果在同一配置文件中重复了,会抛错,但是如果不是同一配置文件中,会发生覆盖。
循环引用:A 依赖 B,而 B 依赖 A。或 A 依赖 B,B 依赖 C,而 C 依赖 A。
默认情况下,Spring 允许循环依赖,当然如果你在 A 的构造方法中依赖 B,在 B 的构造方法中依赖 A 是不行的。

再看loadBeanDefinitions(beanFactory) 方法,这个方法将根据配置,加载各个 Bean,然后放到 BeanFactory 中。先贴上源码:AbstractXmlApplicationContext类中

//实现父类抽象的载入Bean定义方法
	@Override
	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
		// Create a new XmlBeanDefinitionReader for the given BeanFactory.
		//创建XmlBeanDefinitionReader,即创建Bean读取器,并通过回调设置到容器中去,容  器使用该读取器读取Bean定义资源
		XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

		// Configure the bean definition reader with this context's
		// resource loading environment.
		//为Bean读取器设置Spring资源加载器,AbstractXmlApplicationContext的
		//祖先父类AbstractApplicationContext继承DefaultResourceLoader,因此,容器本身也是一个资源加载器
		beanDefinitionReader.setEnvironment(this.getEnvironment());
		beanDefinitionReader.setResourceLoader(this);
		//为Bean读取器设置SAX xml解析器
		beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

		// Allow a subclass to provide custom initialization of the reader,
		// then proceed with actually loading the bean definitions.
		//当Bean读取器读取Bean定义的Xml资源文件时,启用Xml的校验机制
		initBeanDefinitionReader(beanDefinitionReader);
		//Bean读取器真正实现加载的方法
		loadBeanDefinitions(beanDefinitionReader);
	}

这个源码中我们重点看loadBeanDefinitions(beanDefinitionReader);,再点进去源码:

//Xml Bean读取器加载Bean定义资源
	protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
		//获取Bean定义资源的定位
		Resource[] configResources = getConfigResources();
		if (configResources != null) {
			//Xml Bean读取器调用其父类AbstractBeanDefinitionReader读取定位
			//的Bean定义资源
			reader.loadBeanDefinitions(configResources);
		}
		//如果子类中获取的Bean定义资源定位为空,则获取FileSystemXmlApplicationContext构造方法中setConfigLocations方法设置的资源
		String[] configLocations = getConfigLocations();
		if (configLocations != null) {
			//Xml Bean读取器调用其父类AbstractBeanDefinitionReader读取定位
			//的Bean定义资源
			reader.loadBeanDefinitions(configLocations);
		}
	}

在这段源码中我么可以看到2个reader.loadBeanDefinitions()方法,其实两个最终都到了:
AbstractBeanDefinitionReader类中:

	//重载方法,调用loadBeanDefinitions(String);
	@Override
	public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
		Assert.notNull(locations, "Location array must not be null");
		int counter = 0;
		for (String location : locations) {
			counter += loadBeanDefinitions(location);
		}
		return counter;
	}

这个方法里面,for循环每一个文件是一个resource,最终返回 counter,表示总共加载了多少的 BeanDefinition。
进入loadBeanDefinitions(resource);方法,看源码:
XmlBeanDefinitionReader类中的:

//这里是载入XML形式Bean定义资源文件方法
	public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
		Assert.notNull(encodedResource, "EncodedResource must not be null");
		if (logger.isInfoEnabled()) {
			logger.info("Loading XML bean definitions from " + encodedResource.getResource());
		}

		Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
		if (currentResources == null) {
			currentResources = new HashSet<>(4);
			this.resourcesCurrentlyBeingLoaded.set(currentResources);
		}
		if (!currentResources.add(encodedResource)) {
			throw new BeanDefinitionStoreException(
					"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
		}
		try {
			//将资源文件转为InputStream的IO流
			InputStream inputStream = encodedResource.getResource().getInputStream();
			try {
				//从InputStream中得到XML的解析源
				InputSource inputSource = new InputSource(inputStream);
				if (encodedResource.getEncoding() != null) {
					inputSource.setEncoding(encodedResource.getEncoding());
				}
				//这里是具体的读取过程
				return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
			}
			finally {
				//关闭从Resource中得到的IO流
				inputStream.close();
			}
		}
		catch (IOException ex) {
			throw new BeanDefinitionStoreException(
					"IOException parsing XML document from " + encodedResource.getResource(), ex);
		}
		finally {
			currentResources.remove(encodedResource);
			if (currentResources.isEmpty()) {
				this.resourcesCurrentlyBeingLoaded.remove();
			}
		}
	}

这个源码的核心在doLoadBeanDefinitions(inputSource, encodedResource.getResource());继续进源码:

//从特定XML文件中实际载入Bean定义资源的方法
	protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
			throws BeanDefinitionStoreException {
		try {
			//将XML文件转换为DOM对象,解析过程由documentLoader实现
			Document doc = doLoadDocument(inputSource, resource);
			//这里是启动对Bean定义解析的详细过程,该解析过程会用到Spring的Bean配置规则
			return registerBeanDefinitions(doc, resource);
		}
		catch (BeanDefinitionStoreException ex) {
			throw ex;
		}
		catch (SAXParseException ex) {
			throw new XmlBeanDefinitionStoreException(resource.getDescription(),
					"Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);
		}
		catch (SAXException ex) {
			throw new XmlBeanDefinitionStoreException(resource.getDescription(),
					"XML document from " + resource + " is invalid", ex);
		}
		catch (ParserConfigurationException ex) {
			throw new BeanDefinitionStoreException(resource.getDescription(),
					"Parser configuration exception parsing XML from " + resource, ex);
		}
		catch (IOException ex) {
			throw new BeanDefinitionStoreException(resource.getDescription(),
					"IOException parsing XML document from " + resource, ex);
		}
		catch (Throwable ex) {
			throw new BeanDefinitionStoreException(resource.getDescription(),
					"Unexpected exception parsing XML document from " + resource, ex);
		}
	}

在这个方法里面可以看到doLoadDocument(inputSource, resource);方法是将 xml 文件转换为 Document 对象,然后继续进源码:

	//按照Spring的Bean语义要求将Bean定义资源解析并转换为容器内部数据结构
	public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
		//得到BeanDefinitionDocumentReader来对xml格式的BeanDefinition解析
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		//获得容器中注册的Bean数量
		int countBefore = getRegistry().getBeanDefinitionCount();
		//解析过程入口,这里使用了委派模式,BeanDefinitionDocumentReader只是个接口,
		//具体的解析实现过程有实现类DefaultBeanDefinitionDocumentReader完成
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
		//统计解析的Bean数量
		return getRegistry().getBeanDefinitionCount() - countBefore;
	}

这个方法里面看:documentReader.registerBeanDefinitions(doc, createReaderContext(resource));点进去:

//根据Spring DTD对Bean的定义规则解析Bean定义Document对象
	@Override
	public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
		//获得XML描述符
		this.readerContext = readerContext;
		logger.debug("Loading bean definitions");
		//获得Document的根元素
		Element root = doc.getDocumentElement();
		doRegisterBeanDefinitions(root);
	}

里面的doRegisterBeanDefinitions(root);方法就是从 xml 根节点开始解析文件,经过很多的步骤,一个配置文件终于转换为一颗 DOM 树了,注意,这里指的是其中一个配置文件,不是所有的,可以看到上面有个 for 循环的(loadBeanDefinitions(resource);是在for循环里面的),进入doRegisterBeanDefinitions(root);方法,


	protected void doRegisterBeanDefinitions(Element root) {
		// Any nested <beans> elements will cause recursion in this method. In
		// order to propagate and preserve <beans> default-* attributes correctly,
		// keep track of the current (parent) delegate, which may be null. Create
		// the new (child) delegate with a reference to the parent for fallback purposes,
		// then ultimately reset this.delegate back to its original (parent) reference.
		// this behavior emulates a stack of delegates without actually necessitating one.

		//具体的解析过程由BeanDefinitionParserDelegate实现,
		//BeanDefinitionParserDelegate中定义了Spring Bean定义XML文件的各种元素
		BeanDefinitionParserDelegate parent = this.delegate;
		this.delegate = createDelegate(getReaderContext(), root, parent);

		if (this.delegate.isDefaultNamespace(root)) {
			String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
			if (StringUtils.hasText(profileSpec)) {
				String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
						profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
				if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
					if (logger.isInfoEnabled()) {
						logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
								"] not matching: " + getReaderContext().getResource());
					}
					return;
				}
			}
		}

		//在解析Bean定义之前,进行自定义的解析,增强解析过程的可扩展性
		preProcessXml(root);
		//从Document的根元素开始进行Bean定义的Document对象
		parseBeanDefinitions(root, this.delegate);
		//在解析Bean定义之后,进行自定义的解析,增加解析过程的可扩展性
		postProcessXml(root);

		this.delegate = parent;
	}

在这里开始就是真正的解析xml parseBeanDefinitions(root, this.delegate);这个方法往里面

//使用Spring的Bean规则从Document的根元素开始进行Bean定义的Document对象
	protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
		//Bean定义的Document对象使用了Spring默认的XML命名空间
		if (delegate.isDefaultNamespace(root)) {
			//获取Bean定义的Document对象根元素的所有子节点
			NodeList nl = root.getChildNodes();
			for (int i = 0; i < nl.getLength(); i++) {
				Node node = nl.item(i);
				//获得Document节点是XML元素节点
				if (node instanceof Element) {
					Element ele = (Element) node;
					//Bean定义的Document的元素节点使用的是Spring默认的XML命名空间
					if (delegate.isDefaultNamespace(ele)) {
						//使用Spring的Bean规则解析元素节点
						parseDefaultElement(ele, delegate);
					}
					else {
						//没有使用Spring默认的XML命名空间,则使用用户自定义的解//析规则解析元素节点
						delegate.parseCustomElement(ele);
					}
				}
			}
		}
		else {
			//Document的根节点没有使用Spring默认的命名空间,则使用用户自定义的
			//解析规则解析Document根节点
			delegate.parseCustomElement(root);
		}
	}

在这里就是解析Bean定义资源Document对象的普通元素

代码到这里之后呢,Bean容器就已经算是初始化完成了。然后无偶们回到refresh() 方法,就是文章前部分的那个refresh() 方法…TvT
再贴一下refresh() 方法的源码吧,方便阅读:

@Override
public void refresh() throws BeansException, IllegalStateException {
   // 来个锁,不然 refresh() 还没结束,你又来个启动或销毁容器的操作,那不就乱套了嘛
   synchronized (this.startupShutdownMonitor) {

      // 准备工作,记录下容器的启动时间、标记“已启动”状态、处理配置文件中的占位符
      prepareRefresh();

      // 这步比较关键,这步完成后,配置文件就会解析成一个个 Bean 定义,注册到 BeanFactory 中,
      // 当然,这里说的 Bean 还没有初始化,只是配置信息都提取出来了,
      // 注册也只是将这些信息都保存到了注册中心(说到底核心是一个 beanName-> beanDefinition 的 map)
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

      // 设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean
      // 这块待会会展开说
      prepareBeanFactory(beanFactory);

      try {
         // 【这里需要知道 BeanFactoryPostProcessor 这个知识点,Bean 如果实现了此接口,
         // 那么在容器初始化以后,Spring 会负责调用里面的 postProcessBeanFactory 方法。】

         // 这里是提供给子类的扩展点,到这里的时候,所有的 Bean 都加载、注册完成了,但是都还没有初始化
         // 具体的子类可以在这步的时候添加一些特殊的 BeanFactoryPostProcessor 的实现类或做点什么事
         postProcessBeanFactory(beanFactory);
         // 调用 BeanFactoryPostProcessor 各个实现类的 postProcessBeanFactory(factory) 回调方法
         invokeBeanFactoryPostProcessors(beanFactory);          



         // 注册 BeanPostProcessor 的实现类,注意看和 BeanFactoryPostProcessor 的区别
         // 此接口两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
         // 两个方法分别在 Bean 初始化之前和初始化之后得到执行。这里仅仅是注册,之后会看到回调这两方法的时机
         registerBeanPostProcessors(beanFactory);

         // 初始化当前 ApplicationContext 的 MessageSource,国际化这里就不展开说了,不然没完没了了
         initMessageSource();

         // 初始化当前 ApplicationContext 的事件广播器,这里也不展开了
         initApplicationEventMulticaster();

         // 从方法名就可以知道,典型的模板方法(钩子方法),不展开说
         // 具体的子类可以在这里初始化一些特殊的 Bean(在初始化 singleton beans 之前)
         onRefresh();

         // 注册事件监听器,监听器需要实现 ApplicationListener 接口。这也不是我们的重点,过
         registerListeners();

         // 重点,重点,重点
         // 初始化所有的 singleton beans
         //(lazy-init 的除外)
         finishBeanFactoryInitialization(beanFactory);

         // 最后,广播事件,ApplicationContext 初始化完成,不展开
         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.
         // 销毁已经初始化的 singleton 的 Beans,以免有些 bean 会一直占用资源
         destroyBeans();

         // Reset 'active' flag.
         cancelRefresh(ex);

         // 把异常往外抛
         throw ex;
      }

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

这个注释相当清楚,我们直接来看finishBeanFactoryInitialization(beanFactory);方法吧,到这一步为止BeanFactory 已经创建完成,并且所有的实现了 BeanFactoryPostProcessor 接口的 Bean 都已经初始化并且其中的 postProcessBeanFactory(factory) 方法已经得到回调执行了。而且 Spring 已经“手动”注册了一些特殊的 Bean,如 ‘environment’、‘systemProperties’ 等。剩下的就是初始化 singleton beans 了,我们知道它们是单例的,如果没有设置懒加载,那么 Spring 会在接下来初始化所有的 singleton beans。点进去看源码:

	//对配置了lazy-init属性的Bean进行预实例化处理
	protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
		// Initialize conversion service for this context.
		//这是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));
		}

		// Register a default embedded value resolver if no bean post-processor
		// (such as a PropertyPlaceholderConfigurer bean) registered any before:
		// at this point, primarily for resolution in annotation attribute values.
		if (!beanFactory.hasEmbeddedValueResolver()) {
			beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
		}

		// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
		String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
		for (String weaverAwareName : weaverAwareNames) {
			getBean(weaverAwareName);
		}

		// Stop using the temporary ClassLoader for type matching.
		//为了类型匹配,停止使用临时的类加载器
		beanFactory.setTempClassLoader(null);

		// Allow for caching all bean definition metadata, not expecting further changes.
		//缓存容器中所有注册的BeanDefinition元数据,以防被修改
		beanFactory.freezeConfiguration();

		// Instantiate all remaining (non-lazy-init) singletons.
		//对配置了lazy-init属性的单态模式Bean进行预实例化处理
		beanFactory.preInstantiateSingletons();
	}

在这段代码中:首先初始化名字为 “conversionService” 的 Bean,为什么是conversionService 呢?原因是注册这个bean之后,类似于前端传给后端的非基础类型和基础类型的包装类之外,其他的就可以考虑采用ConversionService来进行类型等的转换,初始化这个 “conversionService” 实在上面源码中的beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));进行的。然后直接跳过来到beanFactory.preInstantiateSingletons();这个方法,这里开始初始化。点进去:
DefaultListableBeanFactory这个类中

//对配置lazy-init属性单态Bean的预实例化
	@Override
	public void preInstantiateSingletons() throws BeansException {
		if (this.logger.isDebugEnabled()) {
			this.logger.debug("Pre-instantiating singletons in " + this);
		}

		// Iterate over a copy to allow for init methods which in turn register new bean definitions.
		// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

		// Trigger initialization of all non-lazy singleton beans...
		for (String beanName : beanNames) {
			//获取指定名称的Bean定义
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			//Bean不是抽象的,是单态模式的,且lazy-init属性配置为false
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
				//如果指定名称的bean是创建容器的Bean
				if (isFactoryBean(beanName)) {
					//FACTORY_BEAN_PREFIX=”&”,当Bean名称前面加”&”符号
					//时,获取的是产生容器对象本身,而不是容器产生的Bean.
					//调用getBean方法,触发容器对Bean实例化和依赖注入过程
					final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
					//标识是否需要预实例化
					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(beanName);
				}
			}
		}

		// Trigger post-initialization callback for all applicable beans...
		for (String beanName : beanNames) {
			Object singletonInstance = getSingleton(beanName);
			if (singletonInstance instanceof SmartInitializingSingleton) {
				final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
				if (System.getSecurityManager() != null) {
					AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
						smartSingleton.afterSingletonsInstantiated();
						return null;
					}, getAccessControlContext());
				}
				else {
					smartSingleton.afterSingletonsInstantiated();
				}
			}
		}
	}

在这段源码中,this.beanDefinitionNames 保存了所有的 beanNames,然后再循环,判断非抽象、非懒加载的 singletons,如果是FactoryBeanFactoryBean 的话,在 beanName 前面加上 ‘&’ 符号,再调用getBean(beanName);,如果是普通的bean,那么直接getBean(beanName);,这里都是在循环中的,循环结束后,所有的非单例bean就初始化完成了,接着下面如果我们定义的 bean 是实现了 SmartInitializingSingleton 接口的,那么在smartSingleton.afterSingletonsInstantiated();这里得到回调,我们直接进入getBean()方法:
可以看到最终到了AbstractBeanFactory类的doGetBean方法:

//真正实现向IOC容器获取Bean的功能,也是触发依赖注入功能的地方
	protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

		//根据指定的名称获取被管理Bean的名称,剥离指定名称中对容器的相关依赖
		//如果指定的是别名,将别名转换为规范的Bean名称
		final String beanName = transformedBeanName(name);
		Object bean;

		// Eagerly check singleton cache for manually registered singletons.
		//先从缓存中取是否已经有被创建过的单态类型的Bean
		//对于单例模式的Bean整个IOC容器中只创建一次,不需要重复创建
		Object sharedInstance = getSingleton(beanName);
		//IOC容器创建单例模式Bean实例对象
		if (sharedInstance != null && args == null) {
			if (logger.isDebugEnabled()) {
				//如果指定名称的Bean在容器中已有单例模式的Bean被创建
				//直接返回已经创建的Bean
				if (isSingletonCurrentlyInCreation(beanName)) {
					logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
							"' that is not fully initialized yet - a consequence of a circular reference");
				}
				else {
					logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}
			//获取给定Bean的实例对象,主要是完成FactoryBean的相关处理
			//注意:BeanFactory是管理容器中Bean的工厂,而FactoryBean是
			//创建创建对象的工厂Bean,两者之间有区别
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

		else {
			// Fail if we're already creating this bean instance:
			// We're assumably within a circular reference.
			//缓存没有正在创建的单例模式Bean
			//缓存中已经有已经创建的原型模式Bean
			//但是由于循环引用的问题导致实例化对象失败
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

			// Check if bean definition exists in this factory.
			//对IOC容器中是否存在指定名称的BeanDefinition进行检查,首先检查是否
			//能在当前的BeanFactory中获取的所需要的Bean,如果不能则委托当前容器
			//的父级容器去查找,如果还是找不到则沿着容器的继承体系向父级容器查找
			BeanFactory parentBeanFactory = getParentBeanFactory();
			//当前容器的父级容器存在,且当前容器中不存在指定名称的Bean
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				// Not found -> check parent.
				//解析指定Bean名称的原始名称
				String nameToLookup = originalBeanName(name);
				if (parentBeanFactory instanceof AbstractBeanFactory) {
					return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
							nameToLookup, requiredType, args, typeCheckOnly);
				}
				else if (args != null) {
					// Delegation to parent with explicit args.
					//委派父级容器根据指定名称和显式的参数查找
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else {
					// No args -> delegate to standard getBean method.
					//委派父级容器根据指定名称和类型查找
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
			}

			//创建的Bean是否需要进行类型验证,一般不需要
			if (!typeCheckOnly) {
				//向容器标记指定的Bean已经被创建
				markBeanAsCreated(beanName);
			}

			try {
				//根据指定Bean名称获取其父级的Bean定义
				//主要解决Bean继承时子类合并父类公共属性问题
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);

				// Guarantee initialization of beans that the current bean depends on.
				//获取当前Bean所有依赖Bean的名称
				String[] dependsOn = mbd.getDependsOn();
				//如果当前Bean有依赖Bean
				if (dependsOn != null) {
					for (String dep : dependsOn) {
						if (isDependent(beanName, dep)) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
						}
						//递归调用getBean方法,获取当前Bean的依赖Bean
						registerDependentBean(dep, beanName);
						//把被依赖Bean注册给当前依赖的Bean
						getBean(dep);
					}
				}

				// Create bean instance.
				//创建单例模式Bean的实例对象
				if (mbd.isSingleton()) {
					//这里使用了一个匿名内部类,创建Bean实例对象,并且注册给所依赖的对象
					sharedInstance = getSingleton(beanName, () -> {
						try {
							//创建一个指定Bean实例对象,如果有父级继承,则合并子类和父类的定义
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							// Explicitly remove instance from singleton cache: It might have been put there
							// eagerly by the creation process, to allow for circular reference resolution.
							// Also remove any beans that received a temporary reference to the bean.
							//显式地从容器单例模式Bean缓存中清除实例对象
							destroySingleton(beanName);
							throw ex;
						}
					});
					//获取给定Bean的实例对象
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}

				//IOC容器创建原型模式Bean实例对象
				else if (mbd.isPrototype()) {
					// It's a prototype -> create a new instance.
					//原型模式(Prototype)是每次都会创建一个新的对象
					Object prototypeInstance = null;
					try {
						//回调beforePrototypeCreation方法,默认的功能是注册当前创建的原型对象
						beforePrototypeCreation(beanName);
						//创建指定Bean对象实例
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
						//回调afterPrototypeCreation方法,默认的功能告诉IOC容器指定Bean的原型对象不再创建
						afterPrototypeCreation(beanName);
					}
					//获取给定Bean的实例对象
					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}

				//要创建的Bean既不是单例模式,也不是原型模式,则根据Bean定义资源中
				//配置的生命周期范围,选择实例化Bean的合适方法,这种在Web应用程序中
				//比较常用,如:request、session、application等生命周期
				else {
					String scopeName = mbd.getScope();
					final Scope scope = this.scopes.get(scopeName);
					//Bean定义资源中没有配置生命周期范围,则Bean定义不合法
					if (scope == null) {
						throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
					}
					try {
						//这里又使用了一个匿名内部类,获取一个指定生命周期范围的实例
						Object scopedInstance = scope.get(beanName, () -> {
							beforePrototypeCreation(beanName);
							try {
								return createBean(beanName, mbd, args);
							}
							finally {
								afterPrototypeCreation(beanName);
							}
						});
						//获取给定Bean的实例对象
						bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
					}
					catch (IllegalStateException ex) {
						throw new BeanCreationException(beanName,
								"Scope '" + scopeName + "' is not active for the current thread; consider " +
								"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
								ex);
					}
				}
			}
			catch (BeansException ex) {
				cleanupAfterBeanCreationFailure(beanName);
				throw ex;
			}
		}

		// Check if required type matches the type of the actual bean instance.
		//对创建的Bean实例对象进行类型检查
		if (requiredType != null && !requiredType.isInstance(bean)) {
			try {
				T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
				if (convertedBean == null) {
					throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
				}
				return convertedBean;
			}
			catch (TypeMismatchException ex) {
				if (logger.isDebugEnabled()) {
					logger.debug("Failed to convert bean '" + name + "' to required type '" +
							ClassUtils.getQualifiedName(requiredType) + "'", ex);
				}
				throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
			}
		}
		return (T) bean;
	}

在这段源码中:

  • final String beanName = transformedBeanName(name);获取一个 正确 beanName,处理两种情况,一个是前面说的 FactoryBean(前面带 ‘&’),一个是别名问题,因为这个方法是 getBean,获取 Bean 用的。
  • Object bean 这个是返回值
  • Object sharedInstance = getSingleton(beanName);检查是否已经创建过
  • if (sharedInstance != null && args == null) 这个判断是否已经创建过,还有args 传参其实是 null 的,但是如果 args 不为空的时候,那么意味着调用方不是希望获取 Bean,而是创建 Bean,这在个if中,bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);如果是普通 Bean 的话,直接返回 sharedInstance,如果是 FactoryBean 的话,返回它创建的那个实例对象。然后一系列检查
  • 看到final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);这里之前,检查完成,开始准备创建Bean 了,对于 singleton 的 Bean 来说,容器中还没创建过此 Bean; 对于 prototype 的 Bean 来说,本来就是要创建一个新的 Bean。
  • String[] dependsOn = mbd.getDependsOn();先初始化依赖的所有 Bean, 注意,这里的依赖指的是 depends-on 中定义的依赖
  • registerDependentBean(dep, beanName); 注册依赖关系;然后getBean(dep); 先初始化被依赖项
  • 这里if (mbd.isSingleton()) 如果是单例那么表达式->createBean(beanName, mbd, args);执行创建 Bean
  • 这里else if (mbd.isPrototype())如果是 prototype scope 的,创建 prototype 的实例,prototypeInstance = createBean(beanName, mbd, args);执行创建 Bean
  • 这里else如果不是 singleton 和 prototype 的话,需要委托给相应的实现类来处理,createBean(beanName, mbd, args);
  • if (requiredType != null && !requiredType.isInstance(bean)) 最后检查一下类型是否正确,不正确抛异常,正确流返回创建的bean

然后在进入createBean(beanName, mbd, args);
AbstractAutowireCapableBeanFactory类中:

	//创建Bean实例对象
	@Override
	protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {

		if (logger.isDebugEnabled()) {
			logger.debug("Creating instance of bean '" + beanName + "'");
		}
		RootBeanDefinition mbdToUse = mbd;

		// Make sure bean class is actually resolved at this point, and
		// clone the bean definition in case of a dynamically resolved Class
		// which cannot be stored in the shared merged bean definition.
		//判断需要创建的Bean是否可以实例化,即是否可以通过当前的类加载器加载
		Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
		if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
			mbdToUse = new RootBeanDefinition(mbd);
			mbdToUse.setBeanClass(resolvedClass);
		}

		// Prepare method overrides.
		//校验和准备Bean中的方法覆盖
		try {
			mbdToUse.prepareMethodOverrides();
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
					beanName, "Validation of method overrides failed", ex);
		}

		try {
			// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
			//如果Bean配置了初始化前和初始化后的处理器,则试图返回一个需要创建Bean的代理对象
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			if (bean != null) {
				return bean;
			}
		}
		catch (Throwable ex) {
			throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
					"BeanPostProcessor before instantiation of bean failed", ex);
		}

		try {
			//创建Bean的入口
			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
			if (logger.isDebugEnabled()) {
				logger.debug("Finished creating instance of bean '" + beanName + "'");
			}
			return beanInstance;
		}
		catch (BeanCreationException ex) {
			// A previously detected exception with proper bean creation context already...
			throw ex;
		}
		catch (ImplicitlyAppearedSingletonException ex) {
			// An IllegalStateException to be communicated up to DefaultSingletonBeanRegistry...
			throw ex;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
		}
	}

这里来到AbstractAutowireCapableBeanFactory类主要是为了采用 @Autowired 注解注入属性值(这个很常用,例子很多啊,就普通的依赖注入注解)
然后看到Class<?> resolvedClass = resolveBeanClass(mbd, beanName);确保 BeanDefinition 中的 Class 被加载;
往下Object bean = resolveBeforeInstantiation(beanName, mbdToUse);让 InstantiationAwareBeanPostProcessor 在这一步有机会返回代理,和AOP有关;继续往下Object beanInstance = doCreateBean(beanName, mbdToUse, args);这是重点,当然是点进去啦

	//真正创建Bean的方法
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
			throws BeanCreationException {

						// Instantiate the bean.
						//封装被创建的Bean对象
						BeanWrapper instanceWrapper = null;
						if (mbd.isSingleton()) {
							instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
						}
						if (instanceWrapper == null) {
							instanceWrapper = createBeanInstance(beanName, mbd, args);
						}
						final Object bean = instanceWrapper.getWrappedInstance();
						//获取实例化对象的类型
						Class<?> beanType = instanceWrapper.getWrappedClass();
						if (beanType != NullBean.class) {
							mbd.resolvedTargetType = beanType;
						}

						// Allow post-processors to modify the merged bean definition.
						//调用PostProcessor后置处理器
						synchronized (mbd.postProcessingLock) {
							if (!mbd.postProcessed) {
								try {
									applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				}
				mbd.postProcessed = true;
			}
		}

		// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
		//向容器中缓存单例模式的Bean对象,以防循环引用
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isDebugEnabled()) {
				logger.debug("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			//这里是一个匿名内部类,为了防止循环引用,尽早持有对象的引用
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
		//Bean对象的初始化,依赖注入在此触发
		//这个exposedObject在初始化完成之后返回作为依赖注入完成后的Bean
		Object exposedObject = bean;
		try {
			//将Bean实例对象封装,并且Bean定义中配置的属性值赋值给实例对象
			populateBean(beanName, mbd, instanceWrapper);
			//初始化Bean对象
			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);
			}
		}

		if (earlySingletonExposure) {
			//获取指定名称的已注册的单例模式Bean对象
			Object earlySingletonReference = getSingleton(beanName, false);
			if (earlySingletonReference != null) {
				//根据名称获取的已注册的Bean和正在实例化的Bean是同一个
				if (exposedObject == bean) {
					//当前实例化的Bean初始化完成
					exposedObject = earlySingletonReference;
				}
				//当前Bean依赖其他Bean,并且当发生循环引用时不允许新创建实例对象
				else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
					String[] dependentBeans = getDependentBeans(beanName);
					Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
					//获取当前Bean所依赖的其他Bean
					for (String dependentBean : dependentBeans) {
						//对依赖Bean进行类型检查
						if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
							actualDependentBeans.add(dependentBean);
						}
					}
					if (!actualDependentBeans.isEmpty()) {
						throw new BeanCurrentlyInCreationException(beanName,
								"Bean with name '" + beanName + "' has been injected into other beans [" +
								StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
								"] in its raw version as part of a circular reference, but has eventually been " +
								"wrapped. This means that said other beans do not use the final version of the " +
								"bean. This is often the result of over-eager type matching - consider using " +
								"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
					}
				}
			}
		}

		// Register bean as disposable.
		//注册完成依赖注入的Bean
		try {
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
		}

		return exposedObject;
	}
  • if (instanceWrapper == null)如果进入这个if,说明不是 FactoryBean,instanceWrapper = createBeanInstance(beanName, mbd, args);这里实例化 Bean;下面再说
  • 然后做一些处理比如循环依赖等,直到看到populateBean(beanName, mbd, instanceWrapper);这个代码,这一步负责属性装配,很重要,因为前面的实例只是实例化了,并没有设值,这里就是设值

然后看createBeanInstance(beanName, mbd, args);方法,实例化bean 的

	//创建Bean的实例对象
	protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
		// Make sure bean class is actually resolved at this point.
		//检查确认Bean是可实例化的
		Class<?> beanClass = resolveBeanClass(mbd, beanName);

		//使用工厂方法对Bean进行实例化
		if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
		}

		Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
		if (instanceSupplier != null) {
			return obtainFromSupplier(instanceSupplier, beanName);
		}

		if (mbd.getFactoryMethodName() != null)  {
			//调用工厂方法实例化
			return instantiateUsingFactoryMethod(beanName, mbd, args);
		}

		// Shortcut when re-creating the same bean...
		//使用容器的自动装配方法进行实例化
		boolean resolved = false;
		boolean autowireNecessary = false;
		if (args == null) {
			synchronized (mbd.constructorArgumentLock) {
				if (mbd.resolvedConstructorOrFactoryMethod != null) {
					resolved = true;
					autowireNecessary = mbd.constructorArgumentsResolved;
				}
			}
		}
		if (resolved) {
			if (autowireNecessary) {
				//配置了自动装配属性,使用容器的自动装配实例化
				//容器的自动装配是根据参数类型匹配Bean的构造方法
				return autowireConstructor(beanName, mbd, null, null);
			}
			else {
				//使用默认的无参构造方法实例化
				return instantiateBean(beanName, mbd);
			}
		}

		// Need to determine the constructor...
		//使用Bean的构造方法进行实例化
		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
		if (ctors != null ||
				mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
			//使用容器的自动装配特性,调用匹配的构造方法实例化
			return autowireConstructor(beanName, mbd, ctors, args);
		}

		// No special handling: simply use no-arg constructor.
		//使用默认的无参构造方法实例化
		return instantiateBean(beanName, mbd);
	}
  • Class<?> beanClass = resolveBeanClass(mbd, beanName);首先确保已经加载过这个class
  • 然后if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed())检验一下权限
  • if (instanceSupplier != null) 如果存在 Supplier 回调,则调用 obtainFromSupplier() 进行初始化
  • if (mbd.getFactoryMethodName() != null) 采用工厂方法实例化
  • if (resolved) { if (autowireNecessary) 如果到这里的话是构造函数依赖注入autowireConstructor(beanName, mbd, null, null);
  • else如果没进上面的if (resolved) { if (autowireNecessary)这个if,那么就是无参构造函数 instantiateBean(beanName, mbd);
  • determineConstructorsFromBeanPostProcessors(beanClass, beanName); 这个和后面的if判断 作用是:判断是否采用有参构造函数,如果是那么就采用构造函数依赖注入autowireConstructor(beanName, mbd, ctors, args);

这里我们选无参构造点进去看一下:

	//使用默认的无参构造方法实例化Bean对象
	protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
		try {
			Object beanInstance;
			final BeanFactory parent = this;
			//获取系统的安全管理接口,JDK标准的安全管理API
			if (System.getSecurityManager() != null) {
				//这里是一个匿名内置类,根据实例化策略创建实例对象
				beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
						getInstantiationStrategy().instantiate(mbd, beanName, parent),
						getAccessControlContext());
			}
			else {
				//将实例化的对象封装起来
				beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
			}
			BeanWrapper bw = new BeanWrapperImpl(beanInstance);
			initBeanWrapper(bw);
			return bw;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
		}
	}

在上面的无参构造源码里面,真正的实例化是getInstantiationStrategy().instantiate(mbd, beanName, parent);这段代码,这行执行完成之后,包装成BeanWrapper就直接返回了,我们再点进去instantiate方法看看,在SimpleInstantiationStrategy类中:

//使用初始化策略实例化Bean对象
	@Override
	public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
		// Don't override the class with CGLIB if no overrides.
		//如果Bean定义中没有方法覆盖,则就不需要CGLIB父类类的方法
		if (!bd.hasMethodOverrides()) {
			Constructor<?> constructorToUse;
			synchronized (bd.constructorArgumentLock) {
				//获取对象的构造方法或工厂方法
				constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
				//如果没有构造方法且没有工厂方法
				if (constructorToUse == null) {
					//使用JDK的反射机制,判断要实例化的Bean是否是接口
					final Class<?> clazz = bd.getBeanClass();
					if (clazz.isInterface()) {
						throw new BeanInstantiationException(clazz, "Specified class is an interface");
					}
					try {
						if (System.getSecurityManager() != null) {
							//这里是一个匿名内置类,使用反射机制获取Bean的构造方法
							constructorToUse = AccessController.doPrivileged(
									(PrivilegedExceptionAction<Constructor<?>>) () -> clazz.getDeclaredConstructor());
						}
						else {
							constructorToUse =	clazz.getDeclaredConstructor();
						}
						bd.resolvedConstructorOrFactoryMethod = constructorToUse;
					}
					catch (Throwable ex) {
						throw new BeanInstantiationException(clazz, "No default constructor found", ex);
					}
				}
			}
			//使用BeanUtils实例化,通过反射机制调用”构造方法.newInstance(arg)”来进行实例化
			return BeanUtils.instantiateClass(constructorToUse);
		}
		else {
			// Must generate CGLIB subclass.
			//使用CGLIB来实例化对象
			return instantiateWithMethodInjection(bd, beanName, owner);
		}
	}

在这个方法里面,如果if (!bd.hasMethodOverrides())进入这个if里面,那说明不存在方法覆写,使用 java 反射进行实例化,如果不进入使用 CGLIB进行实例化
下面这个就是反射实例化

BeanUtils.instantiateClass(constructorToUse);	

另外存在方法覆写就是下面这个CGLIB进行实例化

instantiateWithMethodInjection(bd, beanName, owner);

到这里。终于bean被实例化了,然后再看看属性怎么注入的。。。
回到AbstractAutowireCapableBeanFactory类的doCreateBean方法,我们刚才说到createBeanInstance是实例化,接下来就是属性注入方法:populateBean(beanName, mbd, instanceWrapper);点进去看:

//将Bean属性设置到生成的实例对象上
	protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
		if (bw == null) {
			if (mbd.hasPropertyValues()) {
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
			}
			else {
				// Skip property population phase for null instance.
				return;
			}
		}

		// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
		// state of the bean before properties are set. This can be used, for example,
		// to support styles of field injection.
		boolean continueWithPropertyPopulation = true;

		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
						continueWithPropertyPopulation = false;
						break;
					}
				}
			}
		}

		if (!continueWithPropertyPopulation) {
			return;
		}
		//获取容器在解析Bean定义资源时为BeanDefiniton中设置的属性值
		PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

		//对依赖注入处理,首先处理autowiring自动装配的依赖注入
		if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
				mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

			// Add property values based on autowire by name if applicable.
			//根据Bean名称进行autowiring自动装配处理
			if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
				autowireByName(beanName, mbd, bw, newPvs);
			}

			// Add property values based on autowire by type if applicable.
			//根据Bean类型进行autowiring自动装配处理
			if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
				autowireByType(beanName, mbd, bw, newPvs);
			}

			pvs = newPvs;
		}

		//对非autowiring的属性进行依赖注入处理

		boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
		boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);

		if (hasInstAwareBpps || needsDepCheck) {
			if (pvs == null) {
				pvs = mbd.getPropertyValues();
			}
			PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
			if (hasInstAwareBpps) {
				for (BeanPostProcessor bp : getBeanPostProcessors()) {
					if (bp instanceof InstantiationAwareBeanPostProcessor) {
						InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
						pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
						if (pvs == null) {
							return;
						}
					}
				}
			}
			if (needsDepCheck) {
				checkDependencies(beanName, mbd, filteredPds, pvs);
			}
		}

		if (pvs != null) {
			//对属性进行注入
			applyPropertyValues(beanName, mbd, bw, pvs);
		}
	}

这这段源码中,能到这里说明我们的bean已经实例化完成了(工厂方法或者构造方法),开始设置属性值,

  • 在这段源码中往下看,找到if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME)这里表示通过名字找到所有属性值,如果是 bean 依赖,先初始化依赖的 bean。记录依赖关系。
  • 还可以看到if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE)通过类型装配
  • 再往下pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);对采用 @Autowired、@Value 注解的依赖进行设值
  • 最后面applyPropertyValues(beanName, mbd, bw, pvs);就是设置 bean 实例的属性值了

根据名称对属性进行自动依赖注入

//根据名称对属性进行自动依赖注入
	protected void autowireByName(
			String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

		//对Bean对象中非简单属性(不是简单继承的对象,如8中原始类型,字符串,URL等都是简单属性)进行处理
		String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
		for (String propertyName : propertyNames) {
			//如果Spring IOC容器中包含指定名称的Bean
			if (containsBean(propertyName)) {
				//调用getBean方法向IOC容器索取指定名称的Bean实例,迭代触发属性的初始化和依赖注入
				Object bean = getBean(propertyName);
				//为指定名称的属性赋予属性值
				pvs.add(propertyName, bean);
				//指定名称属性注册依赖Bean名称,进行属性依赖注入
				registerDependentBean(propertyName, beanName);
				if (logger.isDebugEnabled()) {
					logger.debug("Added autowiring by name from bean name '" + beanName +
							"' via property '" + propertyName + "' to bean named '" + propertyName + "'");
				}
			}
			else {
				if (logger.isTraceEnabled()) {
					logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
							"' by name: no matching bean found");
				}
			}
		}
	}

根据类型对属性进行自动依赖注入

//根据类型对属性进行自动依赖注入
	protected void autowireByType(
			String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

		//获取用户定义的类型转换器
		TypeConverter converter = getCustomTypeConverter();
		if (converter == null) {
			converter = bw;
		}

		//存放解析的要注入的属性
		Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
		//对Bean对象中非简单属性(不是简单继承的对象,如8中原始类型,字符
		//URL等都是简单属性)进行处理
		String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
		for (String propertyName : propertyNames) {
			try {
				//获取指定属性名称的属性描述器
				PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
				// Don't try autowiring by type for type Object: never makes sense,
				// even if it technically is a unsatisfied, non-simple property.
				//不对Object类型的属性进行autowiring自动依赖注入
				if (Object.class != pd.getPropertyType()) {
					//获取属性的setter方法
					MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
					// Do not allow eager init for type matching in case of a prioritized post-processor.
					//检查指定类型是否可以被转换为目标对象的类型
					boolean eager = !PriorityOrdered.class.isInstance(bw.getWrappedInstance());
					//创建一个要被注入的依赖描述
					DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
					//根据容器的Bean定义解析依赖关系,返回所有要被注入的Bean对象
					Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
					if (autowiredArgument != null) {
						//为属性赋值所引用的对象
						pvs.add(propertyName, autowiredArgument);
					}
					for (String autowiredBeanName : autowiredBeanNames) {
						//指定名称属性注册依赖Bean名称,进行属性依赖注入
						registerDependentBean(autowiredBeanName, beanName);
						if (logger.isDebugEnabled()) {
							logger.debug("Autowiring by type from bean name '" + beanName + "' via property '" +
									propertyName + "' to bean named '" + autowiredBeanName + "'");
						}
					}
					//释放已自动注入的属性
					autowiredBeanNames.clear();
				}
			}
			catch (BeansException ex) {
				throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
			}
		}
	}

到这里,属性注入就完成了,然后回到AbstractAutowireCapableBeanFactory类的doCreateBean方法:populateBean(beanName, mbd, instanceWrapper);执行完成之后,调用的exposedObject = initializeBean(beanName, exposedObject, mbd);,这个方法的作用是处理各种回调。点进去看看吧:

	//初始容器创建的Bean实例对象,为其添加BeanPostProcessor后置处理器
	protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
		//JDK的安全机制验证权限
		if (System.getSecurityManager() != null) {
			//实现PrivilegedAction接口的匿名内部类
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
			//为Bean实例对象包装相关属性,如名称,类加载器,所属容器等信息
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		//对BeanPostProcessor后置处理器的postProcessBeforeInitialization
		//回调方法的调用,为Bean实例初始化前做一些处理
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		//调用Bean实例对象初始化的方法,这个初始化方法是在Spring Bean定义配置
		//文件中通过init-method属性指定的
		try {
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}
		//对BeanPostProcessor后置处理器的postProcessAfterInitialization
		//回调方法的调用,为Bean实例初始化之后做一些处理
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}

这段代码中:

  • invokeAwareMethods(beanName, bean);表示如果 bean 实现了 BeanNameAware、BeanClassLoaderAware 或 BeanFactoryAware 接口,在这里回调,
  • wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);是BeanPostProcessor 的 postProcessBeforeInitialization 回调
  • invokeInitMethods(beanName, wrappedBean, mbd);是处理 bean 中定义的 init-method,或者如果 bean 实现了 InitializingBean 接口,调用 afterPropertiesSet() 方法
  • wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); 这个是BeanPostProcessor 的 postProcessAfterInitialization 回调

好了。到这里,那么IOC的整个过程就完成了,包括容器初始化,bean的初始化、实例化、属性注入,全部跟着源码走了一遍,看起来真复杂,总结一下这个过程吧:

  • Application加载xml AbstractApplicationContext的refresh函数载入Bean定义过程
  • AbstractApplicationContext子类的refreshBeanFactory()方法
  • AbstractRefreshableApplicationContext子类的loadBeanDefinitions方法
  • AbstractBeanDefinitionReader读取Bean定义资源 资源加载器获取要读入的资源
  • XmlBeanDefinitionReader加载Bean定义资源
  • DocumentLoader将Bean定义资源转换为Document对象
  • XmlBeanDefinitionReader解析载入的Bean定义资源文件
  • DefaultBeanDefinitionDocumentReader对Bean定义的Document对象解析
  • BeanDefinitionParserDelegate解析Bean定义资源文件中的元素
  • BeanDefinitionParserDelegate解析元素 解析元素的子元素 解析子元素
  • 解析过后的BeanDefinition在IoC容器中的注册(IoC容器的初始化结束)
  • DefaultListableBeanFactory向IoC容器注册解析后的BeanDefinition(依赖注入开始)
  • AbstractBeanFactory通过getBean向IoC容器获取被管理的Bean
  • AbstractAutowireCapableBeanFactory创建Bean实例对象
  • createBeanInstance方法创建Bean的java实例对象
  • SimpleInstantiationStrategy类使用默认的无参构造方法创建Bean实例化对象
  • populateBean方法对Bean属性的依赖注入 BeanDefinitionValueResolver解析属性值
  • BeanWrapperImpl对Bean属性的依赖注入
    在这里插入图片描述
    最后附加上spring源码的中文注解版:
    https://gitee.com/senhelpa-vivo/spring-framework-5.0.2.RELEASE
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值