`

spring源码浅析之ioc

 
阅读更多

一、什么是IOC

    维基百科上说到:2004年Martin Fowler 提出了“控制反转的”概念,他得出的结论是:依赖对象的获得被反转了。后来为这个创造了一个更好的名字:依赖注入(IOC = Inversion of Control).简单的解释是:系统的运作是通过两个或多个类的合作来实现业务逻辑,这使得每个对象都需要与其合作的对象的引用(依赖关系),这个依赖 对象以前是通过自身实现去获得,现在通过一个容器统一的管理这些依赖关系,从而获得这种依赖的这种实现方式,我们可以成为IOC。

二、Ioc容器系列的设计和实现

spring ioc容器主要有2个系列的容器,一个是实现BeanFactory接口的简单系列容器,一个是ApplicationContext上下文,它作为容器的高级形态存在。



 

 

 

 

三、Ioc的初始化过程

3.1BeanFactory初始化过程

BeanFactory初始化主要分4步:

1,.创建容器配置文件的抽象资源Resource

2.,创建容器BeanFactory

3.创建资源的读取器BeanDefinitionReader

4.从定位的资源位置读取资源



 

下面以XmlBeanFactory源码分析

3.2ApplicationContext初始化过程

3.2.1ApplicationContext初始化过程主要包含3个过程:

 1.Resource定位

 2.BeanDefinition载入

 3.Ioc容器注册BeanDefinition

3.2.2下面以FileSystemXmlApplicationContext为例

3.2.2.1FileSystemXmlApplicationContext的继承体系



 通过下图可以看到FileSystemXmlApplicationContext父类AbstractRefreshableConfigApplicationContext的getConfigLocations()方法在初始化过程中栈信息可以了解到ApplicationContext的定位过程



AbstractApplicationContext的refresh方法

@Override
	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的地方
			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.
                                //设置BeanFactory的后处理
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
                                //调用BeanFactory的后处理,这些后处理器是在bean定义中向容器注册的
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
                                //注册bean的后处理器,在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.
                                //检查监听bean,并向容器注册这些bean
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				//初始化所有non-lazy-init的单例bean
                                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;
			}
		}
	}

 

AbstractXmlApplicationContext的loadBeanDefinitions方法可以得知BeanDefinition载入是通过BeanDefinitionReader载入的

@Override
	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
		// Create a new XmlBeanDefinitionReader for the given BeanFactory.
		XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

		// Configure the bean definition reader with this context's
		// resource loading environment.
		beanDefinitionReader.setEnvironment(this.getEnvironment());
		beanDefinitionReader.setResourceLoader(this);
		beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

		// Allow a subclass to provide custom initialization of the reader,
		// then proceed with actually loading the bean definitions.
		initBeanDefinitionReader(beanDefinitionReader);
		loadBeanDefinitions(beanDefinitionReader);
	}



 XmlBeanDefinitionReader的registerBeanDefinitions方法

@SuppressWarnings("deprecation")
	public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
                //解析xml
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		documentReader.setEnvironment(getEnvironment());
		int countBefore = getRegistry().getBeanDefinitionCount();
                //具体的解析过程在registerBeanDefinitions
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
		return getRegistry().getBeanDefinitionCount() - countBefore;
	}

 DefaultBeanDefinitionDocumentReader的registerBeanDefinitions方法

@Override
	public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
		this.readerContext = readerContext;
		logger.debug("Loading bean definitions");
		Element root = doc.getDocumentElement();
		doRegisterBeanDefinitions(root);
	}

  DefaultBeanDefinitionDocumentReader的doRegisterBeanDefinitions方法

	/**
	 * Register each bean definition within the given root {@code <beans/>} element.
	 */
	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 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)) {
					return;
				}
			}
		}

		preProcessXml(root);
		parseBeanDefinitions(root, this.delegate);
		postProcessXml(root);

		this.delegate = parent;
	}

 

/**
	 * Parse the elements at the root level in the document:
	 * "import", "alias", "bean".
	 * @param root the DOM root element of the document
	 */
	protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
		if (delegate.isDefaultNamespace(root)) {
			NodeList nl = root.getChildNodes();
			for (int i = 0; i < nl.getLength(); i++) {
				Node node = nl.item(i);
				if (node instanceof Element) {
					Element ele = (Element) node;
					if (delegate.isDefaultNamespace(ele)) {
                                                //处理默认<bean>标签
						parseDefaultElement(ele, delegate);
					}
					else {
                                                //处理自定义标签 (i.e.  AOP,CONTENT,JDBC)
                                                //自定义标签分4步
                                                //1、提供一个xsd文件,负责对xml的标签<datasource>进行校验
                                                //2、定义一个BeanDefinitionParser负责解析xml,并将必要的信息放入spring中
                                                //3、定义个NamespaceHandler,由sping框架的调用入口。这也是我们自定义xml解析的入口
                                                //4、配置schema和handler
						delegate.parseCustomElement(ele);
					}
				}
			}
		}
		else {
			delegate.parseCustomElement(root);
		}
	}

 

/**
	 * Process the given bean element, parsing the bean definition
	 * and registering it with the registry.
	 */
	protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		if (bdHolder != null) {
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				// Register the final decorated instance.
                                //向ioc容器注册解析的BeanDefinition
				BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
			}
			catch (BeanDefinitionStoreException ex) {
				getReaderContext().error("Failed to register bean definition with name '" +
						bdHolder.getBeanName() + "'", ele, ex);
			}
			// Send registration event.
			getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
		}
	}

 

 DefaultListableBeanFactory的registerBeanDefinition方法

@Override
	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) {
                        //如果设置为不允许覆盖时,注册相同名称的bean将抛出异常
			if (!isAllowBeanDefinitionOverriding()) {
				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 {
                       //正常BeanDefinition的注册过程
			this.beanDefinitionNames.add(beanName);
			this.manualSingletonNames.remove(beanName);
			this.frozenBeanDefinitionNames = null;
		}
		this.beanDefinitionMap.put(beanName, beanDefinition);

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

 

四、Ioc容器的依赖注入

ApplicationContext依赖的BeanFactory默认是DefaultListableBeanFactory



 下面以DefaultListableBeanFactory的基类AbstractBeanFactory的getBean实现为入口进一步了解依赖注入过程

@SuppressWarnings("unchecked")
	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.
                //先从缓存中取得单例的bean
		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);
		}

		else {
			// Fail if we're already creating this bean instance:
			// We're assumably within a circular reference.
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

			// Check if bean definition exists in this factory.
                        //检查definition 是否存在,没有从双亲取,依次类推
			BeanFactory parentBeanFactory = getParentBeanFactory();
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				// Not found -> check parent.
				String nameToLookup = originalBeanName(name);
				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);
				}
			}

			if (!typeCheckOnly) {
				markBeanAsCreated(beanName);
			}

			try {
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);

				// Guarantee initialization of beans that the current bean depends on.
                                //获取当前bean依赖bean,出发getBean的递归调用
				String[] dependsOn = mbd.getDependsOn();
				if (dependsOn != null) {
					for (String dependsOnBean : dependsOn) {
						if (isDependent(beanName, dependsOnBean)) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
						}
						registerDependentBean(dependsOnBean, beanName);
						getBean(dependsOnBean);
					}
				}

				// Create bean instance.
				if (mbd.isSingleton()) {
                                       //通过createBean方法创建单例
					sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
						@Override
						public Object getObject() throws BeansException {
							try {
								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.
								destroySingleton(beanName);
								throw ex;
							}
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}

				else if (mbd.isPrototype()) {
					// It's a prototype -> create a new instance.
					Object prototypeInstance = null;
					try {
						beforePrototypeCreation(beanName);
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
						afterPrototypeCreation(beanName);
					}
					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}

				else {
					String scopeName = mbd.getScope();
					final Scope scope = this.scopes.get(scopeName);
					if (scope == null) {
						throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
					}
					try {
						Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
							@Override
							public Object getObject() throws BeansException {
								beforePrototypeCreation(beanName);
								try {
									return createBean(beanName, mbd, args);
								}
								finally {
									afterPrototypeCreation(beanName);
								}
							}
						});
						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.
		if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
			try {
				return getTypeConverter().convertIfNecessary(bean, requiredType);
			}
			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;
	}

 

 本文spring为4.1.6版本

 

  • 大小: 113.1 KB
  • 大小: 86.3 KB
  • 大小: 105.2 KB
  • 大小: 66.6 KB
  • 大小: 68.1 KB
  • 大小: 38.4 KB
  • 大小: 32.2 KB
  • 大小: 39.8 KB
  • 大小: 107.7 KB
  • 大小: 24.6 KB
  • 大小: 83.4 KB
分享到:
评论

相关推荐

    Spring源码分析_Spring_IOC

    ### Spring源码分析_Spring_IOC:深入理解Spring的IOC容器机制 #### 基本概念与核心作用 在探讨Spring框架的核心组件之一——IOC(Inversion of Control,控制反转)容器之前,首先需要理解它在Spring框架中的角色...

    spring_ioc

    这是spring_ioc部分的内容。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。...

    Spring源代码解析(一):IOC容器.doc

    在Spring源代码解析的第一部分,我们将聚焦于IOC容器,特别是BeanFactory接口,它是所有Spring容器的基础。 BeanFactory接口是Spring的基石,它定义了基本的容器操作,如获取Bean、检查Bean是否存在、确定Bean的...

    Spring源代码解析

    Spring源代码解析(一):IOC容器 Spring源代码解析(二):IoC容器在Web容器中的启动 Spring源代码解析(三):Spring JDBC Spring源代码解析(四):Spring MVC Spring源代码解析(五):Spring AOP获取Proxy Spring源...

    springIoc实现原理

    Spring Ioc(Inversion of Control,控制反转)是Spring框架的核心特性之一,它改变了传统应用程序中对象的创建和管理方式。在传统的软件设计中,对象的创建和依赖关系的维护通常由代码自身来完成,而在Spring Ioc中...

    Spring源代码解析.rar

    Spring源代码解析1:IOC容器.doc Spring源代码解析2:IoC容器在Web容器中的启动.doc Spring源代码解析3:Spring JDBC .doc Spring源代码解析4:Spring MVC .doc Spring源代码解析5:Spring AOP获取Proxy .doc Spring...

    SpringIOC示例源代码

    在这个示例源代码中,我们可以看到多个Java类和一个bean.xml配置文件,这些都是实现Spring IOC的关键组成部分。 首先,让我们了解一下什么是控制反转(IOC)。在传统的程序设计中,对象通常自行创建其依赖项,但在...

    Spring中IoC优点与缺点解析

    Spring 中 IoC 优点与缺点解析 IoC(Inversion of Control)是 Spring 框架中的一种设计模式,它的主要思想是将对象的创建和管理交给容器,从而解耦合对象之间的依赖关系。今天,我们将详细解析 IoC 的优点和缺点。 ...

    springIOC手写框架分析

    springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC...

    spring ioc模块手写demo

    spring ioc模块手写demospring ioc模块手写demospring ioc模块手写demospring ioc模块手写demospring ioc模块手写demospring ioc模块手写demospring ioc模块手写demospring ioc模块手写demospring ioc模块手写demo...

    Spring4 IOC 示例源码

    "spring4_ioc_demo2"可能是项目的主目录,里面包含了相关的Java源代码、配置文件以及可能的测试用例。通过阅读这些源码,我们可以了解如何配置和使用Spring的IOC容器,以及如何实现依赖注入。 9. **实战演练** ...

    spring ioc

    Spring 是一个广泛应用的 Java 应用开发框架,其核心特性之一就是IOC,它极大地简化了软件组件之间的依赖管理。在本文中,我们将深入探讨 Spring IOC 的概念、工作原理以及如何在实际项目中应用。 首先,理解 IOC ...

    Spring IoC源码深度剖析开源架构源码2021.pdf

    标题《Spring IoC源码深度剖析开源架构源码2021.pdf》和描述《Spring IoC源码深度剖析开源架构源码2021.pdf》表明该文档主要面向于分析Spring框架中控制反转(IoC)容器的核心源码,解析和理解其内部的工作机制及...

    Spring整合Mybatis+SpringIOC

    本文将详细介绍Spring如何与Mybatis整合以及Spring的IOC(Inversion of Control,控制反转)机制。 **Spring整合Mybatis** 1. **配置Mybatis-Spring桥接器** 首先,我们需要引入Mybatis和Spring的相关依赖。在`...

    Spring 源代码解析

    Spring源代码解析1:IOC容器;Spring源代码解析2:IoC容器在Web容器中的启动;Spring源代码解析3:Spring JDBC ; Spring源代码解析4:Spring MVC ;Spring源代码解析5:Spring AOP获取Proxy;Spring源代码解析6:...

    Spring IOC源码解读

    Spring IOC,即Inversion of Control(控制反转),是Spring框架的核心特性之一,它负责管理和装配应用程序中的对象。...理解并掌握Spring的IOC源码,对于深入学习Spring框架以及提升系统设计能力具有重要意义。

    Spring源码分析.pdf

    在 Spring 框架中,IOC 容器扮演着核心角色,本文将深入分析 Spring 源码,了解 IOC 容器的实现机制和基本原理。 一、IOC 容器 IOC容器是 Spring 框架的核心组件之一,它提供了一个统一的方式来管理应用程序中的...

    【框架源码篇 01】Spring源码-手写IOC

    在本系列的第一篇【框架源码篇 01】中,我们...在01-手写IoC源码-spring-v1.zip文件中,你将找到逐步实现这个过程的代码示例,这将帮助你加深对Spring IOC的理解。记得阅读和研究这些代码,实践是检验理论的最好方式。

    springioc和spring aop

    总的来说,Spring的IoC和AOP特性极大地提高了代码的可维护性和可扩展性。通过IoC,我们可以编写松耦合、易于测试和管理的代码;通过AOP,我们能将关注点分离,使代码更加模块化,减少重复代码。理解和熟练运用这两种...

    关于spring框架中的ioc的幽默解释.

    通过这些幽默的例子和不同的IoC类型,我们可以看到Spring框架中的IoC如何帮助我们构建更加解耦、灵活和可维护的代码。它不仅简化了对象之间的依赖关系,还提高了系统的可测试性和可扩展性。在实际开发中,根据项目...

Global site tag (gtag.js) - Google Analytics