2,spring中IOC的實現【analyze spring framework source】

接上一篇 1. Introduce how to import the Spring Framework sourcecode into an eclipse project html

一. 結構 java

spring中bean管理設計到下面3個包 node

 

image

core 至關於一個工具類,bean包是對IOC的實現包,context是在bean的基礎擴展功能 spring

 

IOC的實現原理簡介 app

簡單實現 dom

package org.benson; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.core.io.ClassPathResource; public class Test4DebugSpringIOC { ConfigurableListableBeanFactory beanFactory = new DefaultListableBeanFactory();//manage bean factory ClassPathResource resource = new ClassPathResource( "applicationContext.xml");//resource XmlBeanDefinitionReader xmlReader=new XmlBeanDefinitionReader((BeanDefinitionRegistry)beanFactory); //register public Test4DebugSpringIOC() { // TODO load and registered BeanDefinition  xmlReader.loadBeanDefinitions(resource); } public static void main(String[] args) { Test4DebugSpringIOC test4DebugSpring= new Test4DebugSpringIOC(); Test4DebugSpringBean test4DebugSpringBean = (Test4DebugSpringBean) test4DebugSpring.beanFactory .getBean("testAlias"); test4DebugSpringBean.SayHolle(); } }

 

 1,找到bean的定義文件(Resource) eclipse

      如此處classPathResource,用於找到文件位置 ide

 2,把定義文件解析成BeanDefinition對象,用BeanDefinitionReader 工具

  i 調用DefaultDocumentLoader把XML解析成DOC並進行XSD,DTD等格式驗證.
post

 DefaultDocumentLoader調用了SAX的DocumentBuilderFactory.newInstance(),把XML文件解析成一個org.w3c.dom.Document對象

(順帶提句,不能用JDOM,緣由就是內存,此處this.errorHandler也是SAX的一個事件接口,SAX XML解析是事件解析)
int validationMode = getValidationModeForResource(resource);//Validation xml file . XmlBeanDefinitionReader doLoadBeanDefinitions Document doc = this.documentLoader.loadDocument( inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware());//parse to doc . through documentLoader(DefaultDocumentLoader) return registerBeanDefinitions(doc, resource);

ii DefaultBeanDefinitionDocumentReader讀取document中的全部Element. 

registerBeanDefinitions(doc, resource)中調用BeanDefinitionDocumentReader的registerBeanDefinitions方法獲根節點

public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
		this.readerContext = readerContext;

		logger.debug("Loading bean definitions");
		Element root = doc.getDocumentElement();

		doRegisterBeanDefinitions(root);
	}

獲得XML的根節點,調用doRegisterBeanDefinitions

/** * Register each bean definition within the given root {@code <beans/>} element. * @throws IllegalStateException if {@code <beans profile="..."} attribute is present * and Environment property has not been set * @see #setEnvironment */ protected void doRegisterBeanDefinitions(Element root) { ..//profile // 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 = createHelper(readerContext, root, parent); 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)) { parseDefaultElement(ele, delegate);//parse defalut element  } else { delegate.parseCustomElement(ele); } } } } else { delegate.parseCustomElement(root); } }

 parseDefaultElement(ele, delegate),若是發現是bean標籤則調用processBeanDefinition方法

/** * 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); //parse to object of BeanDefinitionHolder if (bdHolder != null) {//if it is not exit. parse it from xml bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); try { // Register the final decorated instance.  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)); } }

iii 調用BeanDefinitionParserDelegate對象完成doc中Element->BeanDefinitionHolder的轉換

/** * Parses the supplied <code>&lt;bean&gt;</code> element. May return <code>null</code> * if there were errors during parse. Errors are reported to the * {@link org.springframework.beans.factory.parsing.ProblemReporter}. */ public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) { String id = ele.getAttribute(ID_ATTRIBUTE); String nameAttr = ele.getAttribute(NAME_ATTRIBUTE); ... ... //vacation AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean); .... return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); }

 

 

 

先得到別名,這裏叫nameAttr,而後各類相關解析

/** * Parse the bean definition itself, without regard to name or aliases. May return * <code>null</code> if problems occurred during the parsing of the bean definition. */ public AbstractBeanDefinition parseBeanDefinitionElement( Element ele, String beanName, BeanDefinition containingBean) { this.parseState.push(new BeanEntry(beanName)); String className = null; if (ele.hasAttribute(CLASS_ATTRIBUTE)) { className = ele.getAttribute(CLASS_ATTRIBUTE).trim(); } try { String parent = null; if (ele.hasAttribute(PARENT_ATTRIBUTE)) { parent = ele.getAttribute(PARENT_ATTRIBUTE); } AbstractBeanDefinition bd = createBeanDefinition(className, parent); parseBeanDefinitionAttributes(ele, beanName, containingBean, bd); bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT)); parseMetaElements(ele, bd); parseLookupOverrideSubElements(ele, bd.getMethodOverrides()); parseReplacedMethodSubElements(ele, bd.getMethodOverrides()); parseConstructorArgElements(ele, bd); parsePropertyElements(ele, bd); parseQualifierElements(ele, bd); bd.setResource(this.readerContext.getResource()); bd.setSource(extractSource(ele)); return bd; }

 

反正所有當成屬性設置到了AbstractBeanDefinition中,具體能夠看AbstractBeanDefinition類

最後返回BeanDefinitionHolder;BeanDefinitionHolder是由beanname+aliasArray+beandefinition組成的一個對象

 

IV 而後回到ii的最後調用BeanDefinitionReaderUtils.registerBeanDefinition註冊beandefine對象,並調BeanDefinitionRegistry接口進行註冊,如DefaultListableBeanFactory

完成轉換後,BeanDefinitionReaderUtils.registerBeanDefinition 調用到 BeanDefinitionRegistry接口實現類的registerBeanDefinition方法把對象放入bean的工廠容器中

* Register the given bean definition with the given bean factory. * @param definitionHolder the bean definition including name and aliases * @param registry the bean factory to register with * @throws BeanDefinitionStoreException if registration failed */ public static void registerBeanDefinition( BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException { // Register bean definition under primary name. String beanName = definitionHolder.getBeanName(); registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); // Register aliases for bean name, if any. String[] aliases = definitionHolder.getAliases(); if (aliases != null) { for (String aliase : aliases) { registry.registerAlias(beanName, aliase); } } }

 在DefaultListableBeanFactory的實現也很簡單了,直接用map添加下就OK了

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { ....//Validation this.beanDefinitionMap.put(beanName, beanDefinition);//add it to beanDefinitionMap  } resetBeanDefinition(beanName); //reset all exist }

 

 3,查找,經過getbean得到bean,用ConfigurableListableBeanFactory,如DefaultListableBeanFactory

這部分功能主要在abstractbeanfactory中完成,若是是singleton(即spring的default)

i   transformedBeanName(name) ,獲得SimpleAliasRegistry 的 map 屬性 aliasMap,轉換爲beanname(別名功能)

ii  Object sharedInstance = getSingleton(beanName); 嘗試從DefaultSingletonBeanRegistry的MAP singletonObjects中拿出bean (singleton功能)

iii  bean = getObjectForBeanInstance(sharedInstance, name, beanName, null) 處理factorybean部分,附 Spring FactoryBean源碼淺析

iv final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); 從bean註冊的信息中找到bean 對應的 BeanDefinition

v return createBean(beanName, mbd, args); 建立新的bean,經過BeanDefinition的描述信息來,並填充到DefaultSingletonBeanRegistry的singletonObjects中

beanfactory的主要代碼,加上了些註釋

 

/** * Return an instance, which may be shared or independent, of the specified bean. * @param name the name of the bean to retrieve * @param requiredType the required type of the bean to retrieve * @param args arguments to use if creating a prototype using explicit arguments to a * static factory method. It is invalid to use a non-null args value in any other case. * @param typeCheckOnly whether the instance is obtained for a type check, * not for actual use * @return an instance of the bean * @throws BeansException if the bean could not be created */ @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); //get true name from attribute aliasMap of SimpleAliasRegistry  Object bean; // Eagerly check singleton cache for manually registered singletons. Object sharedInstance = getSingleton(beanName); //get instance object from the attribute singletonObjects of DefaultSingletonBeanRegistry 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); // it is for that class witch is implement interface factorybean  } 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. 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); } final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);//get BeanDefinition from registered information  checkMergedBeanDefinition(mbd, beanName, args); // Guarantee initialization of beans that the current bean depends on. String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dependsOnBean : dependsOn) { getBean(dependsOnBean); registerDependentBean(dependsOnBean, beanName); } } // Create bean instance. if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() { //create new instance and put in attribute map singletonObjects of DefaultSingletonBeanRegistry 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>() { 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); } } } // 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; }

 

 

 

 

附 bean中的主要結構

主要類,下列類從上往下繼承

SimpleAliasRegistry 用於維護一個 aliasMap,維護別名功能

DefaultSingletonBeanRegistry map 維護 singletonObjects,維護工廠單例,一個工廠一個單例,非N個工廠一個單例

FactoryBeanRegistrySupport

AbstractBeanFactory ,factorybean的主要實現類,其doGetBean,getBean是主要得到bean的入口 ,維護一個mergedBeanDefinitions

AbstractAutowireCapableBeanFactory,configureableBeanFactory的主要實現類,  createBean根據beandefine的信息建立相應的值

DefaultListableBeanFactory ConfigurableListableBeanFactory和BeanDefinitionRegistry接口的主要實現類,維護beanDefiniti信息

 

 

 

image

 

bean中ConfigurableListableBeanFactory接口繼承了bean中的基本接口,DefaultListableBeanFactory是其惟一實現類

接口由於能夠多繼承,因此用來表示系統的結構最合適不過,而JAVA中類單繼承的,通常只是用來實現設計,側重實現功能,由於類層次確定是一條線。

 

2B青年歡樂多啊,沒事研究下spring源碼,繼續補充更新中,有興趣加企鵝一塊兒研究108966750

相關文章
相關標籤/搜索