一、什么是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版本
相关推荐
### Spring源码分析_Spring_IOC:深入理解Spring的IOC容器机制 #### 基本概念与核心作用 在探讨Spring框架的核心组件之一——IOC(Inversion of Control,控制反转)容器之前,首先需要理解它在Spring框架中的角色...
这是spring_ioc部分的内容。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。...
在Spring源代码解析的第一部分,我们将聚焦于IOC容器,特别是BeanFactory接口,它是所有Spring容器的基础。 BeanFactory接口是Spring的基石,它定义了基本的容器操作,如获取Bean、检查Bean是否存在、确定Bean的...
Spring源代码解析(一):IOC容器 Spring源代码解析(二):IoC容器在Web容器中的启动 Spring源代码解析(三):Spring JDBC Spring源代码解析(四):Spring MVC Spring源代码解析(五):Spring AOP获取Proxy Spring源...
Spring Ioc(Inversion of Control,控制反转)是Spring框架的核心特性之一,它改变了传统应用程序中对象的创建和管理方式。在传统的软件设计中,对象的创建和依赖关系的维护通常由代码自身来完成,而在Spring Ioc中...
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...
在这个示例源代码中,我们可以看到多个Java类和一个bean.xml配置文件,这些都是实现Spring IOC的关键组成部分。 首先,让我们了解一下什么是控制反转(IOC)。在传统的程序设计中,对象通常自行创建其依赖项,但在...
Spring 中 IoC 优点与缺点解析 IoC(Inversion of Control)是 Spring 框架中的一种设计模式,它的主要思想是将对象的创建和管理交给容器,从而解耦合对象之间的依赖关系。今天,我们将详细解析 IoC 的优点和缺点。 ...
springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC...
spring ioc模块手写demospring ioc模块手写demospring ioc模块手写demospring ioc模块手写demospring ioc模块手写demospring ioc模块手写demospring ioc模块手写demospring ioc模块手写demospring ioc模块手写demo...
"spring4_ioc_demo2"可能是项目的主目录,里面包含了相关的Java源代码、配置文件以及可能的测试用例。通过阅读这些源码,我们可以了解如何配置和使用Spring的IOC容器,以及如何实现依赖注入。 9. **实战演练** ...
Spring 是一个广泛应用的 Java 应用开发框架,其核心特性之一就是IOC,它极大地简化了软件组件之间的依赖管理。在本文中,我们将深入探讨 Spring IOC 的概念、工作原理以及如何在实际项目中应用。 首先,理解 IOC ...
标题《Spring IoC源码深度剖析开源架构源码2021.pdf》和描述《Spring IoC源码深度剖析开源架构源码2021.pdf》表明该文档主要面向于分析Spring框架中控制反转(IoC)容器的核心源码,解析和理解其内部的工作机制及...
本文将详细介绍Spring如何与Mybatis整合以及Spring的IOC(Inversion of Control,控制反转)机制。 **Spring整合Mybatis** 1. **配置Mybatis-Spring桥接器** 首先,我们需要引入Mybatis和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,即Inversion of Control(控制反转),是Spring框架的核心特性之一,它负责管理和装配应用程序中的对象。...理解并掌握Spring的IOC源码,对于深入学习Spring框架以及提升系统设计能力具有重要意义。
在 Spring 框架中,IOC 容器扮演着核心角色,本文将深入分析 Spring 源码,了解 IOC 容器的实现机制和基本原理。 一、IOC 容器 IOC容器是 Spring 框架的核心组件之一,它提供了一个统一的方式来管理应用程序中的...
在本系列的第一篇【框架源码篇 01】中,我们...在01-手写IoC源码-spring-v1.zip文件中,你将找到逐步实现这个过程的代码示例,这将帮助你加深对Spring IOC的理解。记得阅读和研究这些代码,实践是检验理论的最好方式。
总的来说,Spring的IoC和AOP特性极大地提高了代码的可维护性和可扩展性。通过IoC,我们可以编写松耦合、易于测试和管理的代码;通过AOP,我们能将关注点分离,使代码更加模块化,减少重复代码。理解和熟练运用这两种...
通过这些幽默的例子和不同的IoC类型,我们可以看到Spring框架中的IoC如何帮助我们构建更加解耦、灵活和可维护的代码。它不仅简化了对象之间的依赖关系,还提高了系统的可测试性和可扩展性。在实际开发中,根据项目...