接上一篇 1. Introduce how to import the Spring Framework sourcecode into an eclipse project html
一. 結構 java
spring中bean管理設計到下面3個包 node
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><bean></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信息
bean中ConfigurableListableBeanFactory接口繼承了bean中的基本接口,DefaultListableBeanFactory是其惟一實現類
接口由於能夠多繼承,因此用來表示系統的結構最合適不過,而JAVA中類單繼承的,通常只是用來實現設計,側重實現功能,由於類層次確定是一條線。
2B青年歡樂多啊,沒事研究下spring源碼,繼續補充更新中,有興趣加企鵝一塊兒研究108966750