Spring IOC容器实现原理大致是容器(Map)+反射(Java反射和cglib)。Spring提供丰富的ApplicationContext,以FileSystemXmlApplicationContext来分析IOC容器。
代码中大量使用设计模式-模板模式,若不清楚请先看看模板模式再来看具体分析。分析框架代码时要
多使用查看类继承和调用关系快捷键,快捷键可以设置,我是设置为F1和F4。
注意:
1.本文重在怎么自我分析框架代码,所以对其中解析需自己实际跟踪代码实践方可。
2.spring源代码版本 spring-framework-3.2.1.RELEASE
预览
org.springframework.beans.factory.BeanFactory,IOC容器根接口。
org.springframework.beans.factory.config.BeanDefinition,Bean实例信息描述接口。
org.springframework.core.io.Resource,Spring配置资源文件接口。
org.springframework.core.io.ResourceLoader,加载配置资源文件接口。
org.springframework.beans.factory.support.BeanDefinitionReader,Bean实例信息描述读取。
org.springframework.beans.factory.xml.BeanDefinitionParserDelegate,实际解析Spring配置资源文件。
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory,自动装箱实现类。
IOC容器初始化入口
org.springframework.context.support.FileSystemXmlApplicationContext public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException { super(parent); <span style="white-space:pre"> </span>// 设置Spring配置文件 setConfigLocations(configLocations); if (refresh) { <span style="white-space:pre"> </span>// IOC容器初始化入口,详见其父类AbstractApplicationContext refresh(); } }
刷新IOC容器,完成资源定位、加载、解析、注册等
org.springframework.context.support.AbstractApplicationContext <span style="white-space:pre"> </span>public void refresh() throws BeansException, IllegalStateException { <span style="white-space:pre"> </span>synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. prepareRefresh(); // 获取BeanFactory容器,并完成资源定位、加载、解析、注册 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) { // Destroy already created singletons to avoid dangling resources. destroyBeans(); // Reset 'active' flag. cancelRefresh(ex); // Propagate exception to caller. throw ex; } } } <span style="white-space:pre"> </span>protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { <span style="white-space:pre"> </span>// 刷新BeanFactory,完成资源定位、加载、解析、注册,详见其子类AbstractRefreshableApplicationContext <span style="white-space:pre"> </span>refreshBeanFactory(); ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (logger.isDebugEnabled()) { logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory); } return beanFactory; } org.springframework.context.support.AbstractRefreshableApplicationContext <span style="white-space:pre"> </span>protected final void refreshBeanFactory() throws BeansException { if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try { DefaultListableBeanFactory beanFactory = createBeanFactory(); beanFactory.setSerializationId(getId()); customizeBeanFactory(beanFactory); <span style="white-space:pre"> </span>// 加载BeanDefinitions,详见其子类AbstractXmlApplicationContext loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } <span style="white-space:pre"> </span>}
读取资源文件,准备加载BeanDefition
Org.springframework.context.support.AbstractXmlApplicationContext <span style="white-space:pre"> </span>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); <span style="white-space:pre"> </span>// 加载BeanDefitions loadBeanDefinitions(beanDefinitionReader); } <span style="white-space:pre"> </span>protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException { Resource[] configResources = getConfigResources(); if (configResources != null) { reader.loadBeanDefinitions(configResources); } String[] configLocations = getConfigLocations(); if (configLocations != null) { reader.loadBeanDefinitions(configLocations); } } org.springframework.beans.factory.support.AbstractBeanDefinitionReader <span style="white-space:pre"> </span>public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException { Assert.notNull(locations, "Location array must not be null"); int counter = 0; for (String location : locations) { <span style="white-space:pre"> </span>// 读取资源文件,加载BeanDefitions counter += loadBeanDefinitions(location); } return counter; } <span style="white-space:pre"> </span>public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException { ResourceLoader resourceLoader = getResourceLoader(); if (resourceLoader == null) { throw new BeanDefinitionStoreException( "Cannot import bean definitions from location [" + location + "]: no ResourceLoader available"); } if (resourceLoader instanceof ResourcePatternResolver) { // Resource pattern matching available. try { Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location); int loadCount = loadBeanDefinitions(resources); if (actualResources != null) { for (Resource resource : resources) { actualResources.add(resource); } } if (logger.isDebugEnabled()) { logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]"); } return loadCount; } catch (IOException ex) { throw new BeanDefinitionStoreException( "Could not resolve bean definition resource pattern [" + location + "]", ex); } } else { // Can only load single resources by absolute URL,资源定位 Resource resource = resourceLoader.getResource(location); <span style="white-space:pre"> </span>// 加载资源文件,加载BeanDefitions,详见其子类 int loadCount = loadBeanDefinitions(resource); if (actualResources != null) { actualResources.add(resource); } if (logger.isDebugEnabled()) { logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]"); } return loadCount; } }
入口-解析XML,加载BeanDefinition,注册BeanDefinition
org.springframework.beans.factory.xml.XmlBeanDefinitionReader <span style="white-space:pre"> </span>public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException { return loadBeanDefinitions(new EncodedResource(resource)); } <span style="white-space:pre"> </span>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); if (encodedResource.getEncoding() != null) { inputSource.setEncoding(encodedResource.getEncoding()); } <span style="white-space:pre"> </span>// 加载BeanDefition 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(); } } } <span style="white-space:pre"> </span>protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException { try { int validationMode = getValidationModeForResource(resource); <span style="white-space:pre"> </span>// 获取资源文件的docment Document doc = this.documentLoader.loadDocument( inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware()); <span style="white-space:pre"> </span>// 解析资源文件并注册BeanDefinitions return registerBeanDefinitions(doc, resource); } catch (BeanDefinitionStoreException ex) { throw ex; } catch (SAXParseException ex) { throw new XmlBeanDefinitionStoreException(resource.getDescription(), "Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex); } catch (SAXException ex) { throw new XmlBeanDefinitionStoreException(resource.getDescription(), "XML document from " + resource + " is invalid", ex); } catch (ParserConfigurationException ex) { throw new BeanDefinitionStoreException(resource.getDescription(), "Parser configuration exception parsing XML from " + resource, ex); } catch (IOException ex) { throw new BeanDefinitionStoreException(resource.getDescription(), "IOException parsing XML document from " + resource, ex); } catch (Throwable ex) { throw new BeanDefinitionStoreException(resource.getDescription(), "Unexpected exception parsing XML document from " + resource, ex); } } <span style="white-space:pre"> </span>public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); documentReader.setEnvironment(this.getEnvironment()); int countBefore = getRegistry().getBeanDefinitionCount(); <span style="white-space:pre"> </span>// 加载BeanDefitions并注册,详见其子类DefaultBeanDefinitionDocumentReader <span style="white-space:pre"> </span>documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); return getRegistry().getBeanDefinitionCount() - countBefore; }
具体解析XML,加载BeanDefinition
org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader <span style="white-space:pre"> </span>public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) { this.readerContext = readerContext; logger.debug("Loading bean definitions"); Element root = doc.getDocumentElement(); <span style="white-space:pre"> </span>// 加载、注册BeanDefitions doRegisterBeanDefinitions(root); } <span style="white-space:pre"> </span>protected void doRegisterBeanDefinitions(Element root) { String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE); if (StringUtils.hasText(profileSpec)) { Assert.state(this.environment != null, "environment property must not be null"); String[] specifiedProfiles = StringUtils.tokenizeToStringArray(profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS); if (!this.environment.acceptsProfiles(specifiedProfiles)) { return; } } // 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); <span style="white-space:pre"> </span>// 解析BeanDefinitions parseBeanDefinitions(root, this.delegate); postProcessXml(root); this.delegate = parent; } <span style="white-space:pre"> </span>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); } else { delegate.parseCustomElement(ele); } } } } else { delegate.parseCustomElement(root); } } <span style="white-space:pre"> </span>private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) { if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) { importBeanDefinitionResource(ele); } else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) { processAliasRegistration(ele); } else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) { <span style="white-space:pre"> </span>// 解析bean processBeanDefinition(ele, delegate); } else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) { // recurse doRegisterBeanDefinitions(ele); } } <span style="white-space:pre"> </span>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. 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)); } } <span style="white-space:pre"> </span>protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { <span style="white-space:pre"> </span>// 解析BEAN,将解析的BeanDefinition包装下,实质解析交给委派类 BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); if (bdHolder != null) { bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); try { // 注册BeanDefinition,即注册到BeanFactory中 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)); } }
实质解析XML
org.springframework.beans.factory.xml.BeanDefinitionParserDelegate <span style="white-space:pre"> </span>public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) { String id = ele.getAttribute(ID_ATTRIBUTE); String nameAttr = ele.getAttribute(NAME_ATTRIBUTE); List<String> aliases = new ArrayList<String>(); if (StringUtils.hasLength(nameAttr)) { String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS); aliases.addAll(Arrays.asList(nameArr)); } String beanName = id; if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) { beanName = aliases.remove(0); if (logger.isDebugEnabled()) { logger.debug("No XML 'id' specified - using '" + beanName + "' as bean name and " + aliases + " as aliases"); } } if (containingBean == null) { checkNameUniqueness(beanName, aliases, ele); } <span style="white-space:pre"> </span>// 解析BeanDefinition AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean); if (beanDefinition != null) { if (!StringUtils.hasText(beanName)) { try { if (containingBean != null) { beanName = BeanDefinitionReaderUtils.generateBeanName( beanDefinition, this.readerContext.getRegistry(), true); } else { beanName = this.readerContext.generateBeanName(beanDefinition); // Register an alias for the plain bean class name, if still possible, // if the generator returned the class name plus a suffix. // This is expected for Spring 1.2/2.0 backwards compatibility. String beanClassName = beanDefinition.getBeanClassName(); if (beanClassName != null && beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() && !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) { aliases.add(beanClassName); } } if (logger.isDebugEnabled()) { logger.debug("Neither XML 'id' nor 'name' specified - " + "using generated bean name [" + beanName + "]"); } } catch (Exception ex) { error(ex.getMessage(), ele); return null; } } String[] aliasesArray = StringUtils.toStringArray(aliases); return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); } return null; } <span style="white-space:pre"> </span>// 具体解析就在BeanDefinitionParserDelegate类,若想知道具体怎么解析的,请查看此类即可 <span style="white-space:pre"> </span>public Object parsePropertySubElement(Element ele, BeanDefinition bd, String defaultValueType) { if (!isDefaultNamespace(ele)) { return parseNestedCustomElement(ele, bd); } else if (nodeNameEquals(ele, BEAN_ELEMENT)) { BeanDefinitionHolder nestedBd = parseBeanDefinitionElement(ele, bd); if (nestedBd != null) { nestedBd = decorateBeanDefinitionIfRequired(ele, nestedBd, bd); } return nestedBd; } else if (nodeNameEquals(ele, REF_ELEMENT)) { // A generic reference to any name of any bean. String refName = ele.getAttribute(BEAN_REF_ATTRIBUTE); boolean toParent = false; if (!StringUtils.hasLength(refName)) { // A reference to the id of another bean in the same XML file. refName = ele.getAttribute(LOCAL_REF_ATTRIBUTE); if (!StringUtils.hasLength(refName)) { // A reference to the id of another bean in a parent context. refName = ele.getAttribute(PARENT_REF_ATTRIBUTE); toParent = true; if (!StringUtils.hasLength(refName)) { error("'bean', 'local' or 'parent' is required for <ref> element", ele); return null; } } } if (!StringUtils.hasText(refName)) { error("<ref> element contains empty target attribute", ele); return null; } RuntimeBeanReference ref = new RuntimeBeanReference(refName, toParent); ref.setSource(extractSource(ele)); return ref; } else if (nodeNameEquals(ele, IDREF_ELEMENT)) { return parseIdRefElement(ele); } else if (nodeNameEquals(ele, VALUE_ELEMENT)) { return parseValueElement(ele, defaultValueType); } else if (nodeNameEquals(ele, NULL_ELEMENT)) { // It's a distinguished null value. Let's wrap it in a TypedStringValue // object in order to preserve the source location. TypedStringValue nullHolder = new TypedStringValue(null); nullHolder.setSource(extractSource(ele)); return nullHolder; } else if (nodeNameEquals(ele, ARRAY_ELEMENT)) { return parseArrayElement(ele, bd); } else if (nodeNameEquals(ele, LIST_ELEMENT)) { return parseListElement(ele, bd); } else if (nodeNameEquals(ele, SET_ELEMENT)) { return parseSetElement(ele, bd); } else if (nodeNameEquals(ele, MAP_ELEMENT)) { return parseMapElement(ele, bd); } else if (nodeNameEquals(ele, PROPS_ELEMENT)) { return parsePropsElement(ele); } else { error("Unknown property sub-element: [" + ele.getNodeName() + "]", ele); return null; } }
注册BeanDefinition
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
从上面代码分析中可知道,将BeanDefinition注册到BeanFacotry
org.springframework.beans.factory.support.BeanDefinitionReaderUtils <span style="white-space:pre"> </span>public static void registerBeanDefinition( BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException { // Register bean definition under primary name. String beanName = definitionHolder.getBeanName(); <span style="white-space:pre"> </span>// 具体注册,详见其子类DefaultListableBeanFactory 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); } } } org.springframework.beans.factory.support.DefaultListableBeanFactory <span style="white-space:pre"> </span>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); } } synchronized (this.beanDefinitionMap) { Object 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 (this.logger.isInfoEnabled()) { this.logger.info("Overriding bean definition for bean '" + beanName + "': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]"); } } } else { this.beanDefinitionNames.add(beanName); this.frozenBeanDefinitionNames = null; } this.beanDefinitionMap.put(beanName, beanDefinition); } resetBeanDefinition(beanName); } <span style="white-space:pre"> </span>// 这就是BeanDefinition存放的容器 private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);
至此我们了解了IOC的资源定位、加载、解析、注册,但还未初始化对象和设置属性和依赖关系,
而此行为发生在getBean()中
GetBean初始化对象
org.springframework.context.support.AbstractApplicationContext public Object getBean(String name) throws BeansException { <span style="white-space:pre"> </span>return getBeanFactory().getBean(name); }
上面代码分析中可以知道getBeanFactory()其子类AbstractRefreshableApplicationContext中
实现,getBeanFactory()返回DefaultListableBeanFactory,而getBean(String)在
DefaultListableBeanFactory父类AbstractBeanFactory中
org.springframework.beans.factory.support.AbstractBeanFactory <span style="white-space:pre"> </span>public Object getBean(String name) throws BeansException { <span style="white-space:pre"> </span>return doGetBean(name, null, null, false); } <span style="white-space:pre"> </span>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); } 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); 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>() { 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; }
从doGetBean方法中我们得到很多信息(具体自己跟踪下看看),其中调用了关键方法createBean
详见其子类AbstractAutowireCapableBeanFactory(看类名就知道了)。
初始化对象,设置属性和依赖关系
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory <span style="white-space:pre"> </span>protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) throws BeanCreationException { if (logger.isDebugEnabled()) { logger.debug("Creating instance of bean '" + beanName + "'"); } // Make sure bean class is actually resolved at this point. resolveBeanClass(mbd, beanName); // Prepare method overrides. try { mbd.prepareMethodOverrides(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName, "Validation of method overrides failed", ex); } try { // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. Object bean = resolveBeforeInstantiation(beanName, mbd); if (bean != null) { return bean; } } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", ex); } Object beanInstance = doCreateBean(beanName, mbd, args); if (logger.isDebugEnabled()) { logger.debug("Finished creating instance of bean '" + beanName + "'"); } return beanInstance; }
从上面一步步分析到这里,对IOC容器的实现思路已较清楚,接下来自动装箱的实现自己跟组代码分析吧。
整个代码分析后,本人感触很深,spring框架代码确实是高内聚低耦合,整个分析过后,再回想IOC的实现,
其实没有想象中那么难,本文分析中很多具体的实现还需读者自己去跟踪代码去看看怎么实现的。望读者能一边
跟踪代码一边看本文,若不自己实践操作,仅一眼过去效果不会很大。
若文中存在分析错误,望留言指出,在此非常感谢。