spring 源码_Spring源码分析

一、 Spring 运行原理

  1. Spring 启动时读取应用程序提供的 Bean 配置信息,
  2. 并在 Spring 容器中生成一份相应的Bean 配置注册表;
  3. 然后根据这张注册表实例化 Bean,装配好 Bean 之间的依赖关系,
  4. 将Bean放回bean缓冲池等待上层应用调用;
  5. 应用程序需要使用bean时从Bean缓冲池中获取
  6. 为上层应用提供准备就绪的运行环境。

eed22468c02b26bbb1397f0011d96401.png

二、 Spring 源码分析

1 ApplicationContext

1.1Spring 中 IOC 容器分类

Spring 中有两个主要的容器系列:

1)实现 BeanFactory 接口的简单容器; 只提供了对对象生命周期的管理

2)实现 ApplicationContext 接口的高级容器。 不仅包含了BeanFactory的能力,而且提供了额外的能力。

1.2ApplicationContext 容器介绍

ApplicationContext内部封装了一个BeanFactory对象,来实现对容器的操作,BeanFactory 封装了 bean 的信息,而 ApplicationContext 通过访问 BeanFactory 对象获取 bean 的对象信息 。

ApplicationContext 也 实 现 了 一 系 列 的 BeanFactory 接 口 ( 可 以 说 ApplicationContext 对 BeanFactory 对象实现一种代理)。ApplicationContext 在应用这个 DefaultListableBeanFactory 对象的基础上,不仅实现了BeanFactory 接口提供的功能方法,并且黏合了一些面向应用的功能,如资源/国际化支持/ 框架事件支持等 。

public interface ApplicationContext extends EnvironmentCapable, 
ListableBeanFactory, //继承于 BeanFactory 
HierarchicalBeanFactory,//继承于 BeanFactory 
MessageSource, // 
ApplicationEventPublisher,// 
ResourcePatternResolver //继承 ResourceLoader,用于获取 resource 对象 配置文件

841a590c681c7ab2ca47a465ea0ca244.png

可以看出最终ClassPathXmlApplicationContext 实现了这个接口,就下来就分析ApplicationContext 的启动流程。

2 ClassPathXmlApplicationContext

调用了ClassPathXmlApplicationContext(String configLocation)构造方法;

7ddec73844c0ff5e4da9c2b5eb268525.png

ClassPathXmlApplicationContext(String configLocation)方法又调用了另一个构造方法:

1db82c34cfb1eca10c02e4ea3655a8ba.png

2.1refresh()方法

这个构造方法中有一个重要的方法:refresh()方法 是整个Spring IoC容器初始化的入口方法。

2c5dfbcbf03e810b42c4b9b6cdcf1f3c.png

下面是refresh()方法中的介绍:

红色标记为重要。

cae61eb12ce07be6b8ec07c4aca4178b.png
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) {
				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;
			}
		}
	}

obtainFreshBeanFactory()方法创建Bean工厂,然后才能实现对BeanDefinition的装配。

接下来查看obtainFreshBeanFactory()源码:

ce172b007a35dbb5d5efacbb09015161.png

其中首先执行refreshBeanFactory()方法:查看源码,这里是AbstractRefreshableApplicationContext

6b68c76cdf82cf11a6663993fa6b0d1a.png

这里调用了一个重要的方法createBeanFactory创建了DefaultListableBeanFactory对象;

aff8a87e97548d319f05b928067fd867.png

2.2实例化 Bean 工厂

2.2.1DefaultListableBeanFactory

在 BeanFactory 子类中有一个 DefaultListableBeanFactory 类,它包含了基本 Spirng IoC 容器所具有的重要功能,开发时不论是使用 BeanFactory 系列还是 ApplicationContext 系列来创建容器基本都会使用到 DefaultListableBeanFactory 类,可以这么说,在 spring 中实际上把 它当成默认的 IoC 容器来使用。

e6e469a9b603269b86330c4c7c807f83.png

4145c21a0f60b31467cf5108ee043b9c.png

5d5e27c56eb2a451a03c6ae434fd9c69.png

77026e364acfcd924bc1ed5947185c9a.png

这里的beanFactory最终还是DefaultListableBeanFactory。

f14605256892206ce4c980b2bcea84f1.png

DefaultListableBeanFactory中Map用于解析配置文件后填充,(就是图中的注册表)用于BeanFactory对Bean的实例化。

private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);

接下来分析解析配置文件的代码

2.3解析配置文件

loadBeanDefinitions方法用于加载Bean,传入DefaultListableBeanFactory

987ca05043ed5c8cc523e4df9ad6a4a1.png

f69e00314ddca50363406d107b74d2c6.png

2.3.1XmlBeanDefinitionReader

帮助完成xml解析,吧把Bean的信息放到注册表中,

  1. 首先初始化beanDefinitionReader,
  2. 然后读取初始化完成后的bean,
  3. 最后将对象传入loadBeanDefinitions方法中。

bfb2ec44c716c68a61cdd52b7f128d46.png

这里走容器自身资源,遍历配置文件,每循环一次,就使用loadBeanDefinitions(String location)解析一次,

304b76e582ce20b8d58c7ba5c1c2110b.png

loadBeanDefinitions(String location)中调用构造方法:

ede27e0d92aa955bf5170bd0cecca2fa.png

然后又调用构造方法:

4dbf7bfdd59023f69d654baf0e51085c.png

遍历resource,调用XmlBeanDefinitionreader中的loadBeanDefinitions方法;

a564f4c3fd6dc6ccd043eea8c4d04102.png

9665d89724e1f1b12aa0c7e49be10f68.png

接着调

38be8ee526baf13d2a00ac57c86e8ef0.png

调:

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<EncodedResource>(4);
			this.resourcesCurrentlyBeingLoaded.set(currentResources);
		}
		if (!currentResources.add(encodedResource)) {
			throw new BeanDefinitionStoreException(
					"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
		}
		try {
			InputStream inputStream = encodedResource.getResource().getInputStream();//获取配置文件信息
			try {
				InputSource inputSource = new InputSource(inputStream);//spring解析xml使用sax方式,需要InputSource转化类型
				if (encodedResource.getEncoding() != null) {
					inputSource.setEncoding(encodedResource.getEncoding());
				}
				return doLoadBeanDefinitions(inputSource, encodedResource.getResource());//调用解析
			}
			finally {
				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();
			}
		}
	}

94e344ef901b3ba383501cc5cacdf2a6.png

传入document 和创建读取xml文件的上下文对象

5db2a2f34d2474fccf4b2c646c29b02f.png

b012dceee0bc5330ff100b82825bfd1f.png

b6c1bfc6a251d32df41b0ec0e9d4a598.png

循环遍历root节点

0c290b01361b1cf33d048c0b5406db9c.png

5b97f08164c366eeab7b5e8d79ede300.png

解析完配置文件后就该注册Bean了

3 将 BeanDefiniton 注册到容器中

processBeanDefinition方法:

每次根据解析出来的Bean标签都会创建,返回的BeanDefinitionHolder对象,这个对象是对解析出来结果的定义,并且能完成将解析出的结果注册到Spring Ioc容器中。每次根据解析出来的Bean标签都会创建。

使用了工具类BeanDefinitionReaderUtils中的registerBeanDefinition方法完成注册。

b0c2c28d6c05cf671cb713cec1da293a.png

registerBeanDefinition:首先取出beanName,然后调用registerBeanDefinition

552bd08b9ace46a56841f693b2a8ccef.png

调用:

f755f0355e9cec9ce427b64db09ffe05.png
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {

		Assert.hasText(beanName, "Bean name must not be empty");
		Assert.notNull(beanDefinition, "BeanDefinition must not be null");

		if (beanDefinition instanceof AbstractBeanDefinition) {
			try {
				((AbstractBeanDefinition) beanDefinition).validate();
			}
			catch (BeanDefinitionValidationException ex) {
				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
						"Validation of bean definition failed", ex);
			}
		}

		BeanDefinition oldBeanDefinition;

		oldBeanDefinition = this.beanDefinitionMap.get(beanName);
		if (oldBeanDefinition != null) {
			if (!this.allowBeanDefinitionOverriding) {
				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
						"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
						"': There is already [" + oldBeanDefinition + "] bound.");
			}
			else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
				// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
				if (this.logger.isWarnEnabled()) {
					this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
							" with a framework-generated bean definition ': replacing [" +
							oldBeanDefinition + "] with [" + beanDefinition + "]");
				}
			}
			else {
				if (this.logger.isInfoEnabled()) {
					this.logger.info("Overriding bean definition for bean '" + beanName +
							"': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
				}
			}
		}
		else {
			this.beanDefinitionNames.add(beanName);
			this.manualSingletonNames.remove(beanName);
			this.frozenBeanDefinitionNames = null;
		}
		//将解析出来的配置文件通过key:beanName value:beanDefinition(bean的信息)的形式放入map(注册表中)
		this.beanDefinitionMap.put(beanName, beanDefinition);

		if (oldBeanDefinition != null || containsSingleton(beanName)) {
			resetBeanDefinition(beanName);
		}
	}

完成祖册后,接下来就是实例化Bean

4 Bean 对象的实例化

refresh()中的 finishBeanFactoryInitialization(beanFactory);

084abbe332d18b9b65fa5795e011f0ac.png

实例化单例模式(不是懒加载)的bean

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<String>(this.beanDefinitionNames);//获得beanNames信息

		// Trigger initialization of all non-lazy singleton beans...
		for (String beanName : beanNames) {
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);//获得bean信息
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {//判断是否被实例化
				if (isFactoryBean(beanName)) {
				        //如果没有被实例化,调用getBean方法拿beanName拼上前缀获得相应的FactoyBean
					final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
					boolean isEagerInit;
					if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
						isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
							@Override
							public Boolean run() {
								return ((SmartFactoryBean<?>) factory).isEagerInit();//实例化Bean
							}
						}, getAccessControlContext());
					}
					else {
						isEagerInit = (factory instanceof SmartFactoryBean &&
								((SmartFactoryBean<?>) factory).isEagerInit());
					}
					if (isEagerInit) {
						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(new PrivilegedAction<Object>() {
						@Override
						public Object run() {
							smartSingleton.afterSingletonsInstantiated();
							return null;
						}
					}, getAccessControlContext());
				}
				else {
					smartSingleton.afterSingletonsInstantiated();
				}
			}
		}
	}

5 GetBean

7aff7e26136b9a54c464acd675d7a46f.png

c1207dbae196a6d76328787a76338e0a.png

getBeanFactory()还是之前的那个,返回DefaultListableBeanFactory.

90926d34532270705ec1553604f4ba30.png

DefaultListableBeanFactory下的getBean方法:传入接口的类型

5456a8d5402ddc747632b82274c59372.png

调用的:

public <T> T getBean(Class<T> requiredType, Object... args) throws BeansException {
		Assert.notNull(requiredType, "Required type must not be null");
		//userServiceImpl如果spring中不是通过xml配置的,而是通过注解(key:类名首字母小写value:beanDefinition)
		//beanName就是爱spring ioc容器中缓存的bean对象的唯一标记,根据标记取得对象
		String[] beanNames = getBeanNamesForType(requiredType);
		if (beanNames.length > 1) {
			ArrayList<String> autowireCandidates = new ArrayList<String>();
			for (String beanName : beanNames) {
				if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) {
					autowireCandidates.add(beanName);
				}
			}
			if (autowireCandidates.size() > 0) {
				beanNames = autowireCandidates.toArray(new String[autowireCandidates.size()]);
			}
		}
		if (beanNames.length == 1) {
			return getBean(beanNames[0], requiredType, args);//
		}
		else if (beanNames.length > 1) {
			Map<String, Object> candidates = new HashMap<String, Object>();
			for (String beanName : beanNames) {
				candidates.put(beanName, getBean(beanName, requiredType, args));
			}
			String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
			if (primaryCandidate != null) {
				return getBean(primaryCandidate, requiredType, args);
			}
			String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
			if (priorityCandidate != null) {
				return getBean(priorityCandidate, requiredType, args);
			}
			throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet());
		}
		else if (getParentBeanFactory() != null) {
			return getParentBeanFactory().getBean(requiredType, args);
		}
		else {
			throw new NoSuchBeanDefinitionException(requiredType);
		}
	}

getBean:

37df83e364d2ec3c6e4b6d25051858e9.png

doGetBean:

protected <T> T doGetBean(
			final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
			throws BeansException {

		final String beanName = transformedBeanName(name);
		Object bean;

		// Eagerly check singleton cache for manually registered singletons.
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			if (logger.isDebugEnabled()) {
				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 = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}
              ...
	}

先通过给定的接口类型转化得出接口实现类的名称,然后拿着这个名称作为取key的标记,用标记获得beanDefinition

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值