自定义的Bean定义html
class MyBeanDefinition{ public String id; public String className; public String value; public MyBeanDefinition(String id, String className, String value) { this.id = id; this.className = className; this.value = value; } }
自定义的Bean工厂node
class MyBeanFactory { Map<String, Object> beanMap = new HashMap<>(); public MyBeanFactory(MyBeanDefinition beanDefinition) throws ClassNotFoundException, IllegalAccessException, InstantiationException { Class<?> beanClass = Class.forName(beanDefinition.className); Object bean = beanClass.newInstance(); ((UserService) bean).setName(beanDefinition.value); beanMap.put(beanDefinition.id, bean); } public Object getBean(String id) { return beanMap.get(id); } }
测试傻瓜版IOC容器spring
public class EasyIOC { public static void main(String[] args) throws IllegalAccessException, InstantiationException, ClassNotFoundException { MyBeanDefinition beanDefinition = new MyBeanDefinition("userService", "com.valarchie.UserService", "archie"); MyBeanFactory beanFactory = new MyBeanFactory(beanDefinition); UserService userService = (UserService) beanFactory.getBean("userService"); System.out.println(userService.getName()); } }
按照个人理解,我总结为如下三步设计模式
因此,接下来咱们不会通盘分析整个IOC的流程,由于旁枝细节太多读者看完也云里雾里抓不到重点。
咱们经过分析最重要的这条代码主干线来理解IOC的过程。数组
首先咱们从xml的配置方式开始分析,由于Spring最初的配置方式就是利用xml来进行配置,因此大部分人对xml的配置形式较为熟悉,也比较方便理解。缓存
从ClassPathXmlApplicationContext的构造器开始讲起。app
public class TestSpring { public static void main(String[] args) { // IOC容器的启动就从ClassPathXmlApplicationContext的构造方法开始 ApplicationContext context = new ClassPathXmlApplicationContext("classpath:application.xml"); UserService userService = (UserService) context.getBean("userService"); System.out.println(userService.getName()); } }
进入到构造方法中,调用重载的另外一个构造方法。dom
// 建立ClassPathXmlApplicationContext,加载给定的位置的xml文件,并自动刷新context public ClassPathXmlApplicationContext(String configLocation) throws BeansException { this(new String[] {configLocation}, true, null); }
重载的构造方法中,因为刚才parrent参数传为null,因此不设置父容器。refresh刚才设置为true,流程就会进入refresh()方法中ide
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException { // 因为以前的方法调用将parent设置为null,因此咱们就不分析了 super(parent); // 设置路径数组,并依次对配置路径进行简单占位符替换处理,比较简单,咱们也不进入分析了 setConfigLocations(configLocations); if (refresh) { refresh(); } }
整个refresh()方法中就是IOC容器启动的主干脉络了,Spring采用了模板方法设计模式进行refresh()方法的设计,先规定好整个IOC容器的具体步骤,而后将每个小步骤由各类不一样的子类本身实现。post
全部重要的操做都是围绕着BeanFactory在进行。
在注释当中,咱们详细的列出了每一步方法所完成的事情。ApplicationContext内部持有了FactoryBean的实例。其实ApplicationContext自己最上层的父接口也是BeanFactory,他拓展了BeanFactory以外的功能(提供国际化的消息访问、资源访问,如URL和文件、事件传播、载入多个(有继承关系)上下文)
咱们先经过阅读代码中的注释来了解大概的脉络。
public void refresh() throws BeansException, IllegalStateException { // 先加锁防止启动、结束冲突 synchronized (this.startupShutdownMonitor) { // 在刷新以前作一些准备工做 // 设置启动的时间、相关状态的标志位(活动、关闭)、初始化占位符属性源,并确认 // 每一个标记为必须的属性都是可解析的。 prepareRefresh(); // 获取一个已刷新的BeanFactory实例。 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 定义好Bean工厂的环境特性,例如类加载器,或者后置处理器 prepareBeanFactory(beanFactory); try { // 设置在BeanFactory完成初始化以后作一些后置操做,spring留给子类的扩展。 postProcessBeanFactory(beanFactory); // 启动以前已设置的BeanFactory后置处理器 invokeBeanFactoryPostProcessors(beanFactory); // 注册Bean处理器 registerBeanPostProcessors(beanFactory); // 为咱们的应用上下文设置消息源(i18n) initMessageSource(); // 初始化事件广播器 initApplicationEventMulticaster(); // 初始化特殊的Bean在特殊的Context中,默认实现为空,交给各个具体子类实现 onRefresh(); // 检查监听器并注册 registerListeners(); // 实例化全部非懒加载的Bean finishBeanFactoryInitialization(beanFactory); // 最后一步发布相应的事件 finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } // 若是启动失败的话,要销毁以前建立的Beans。 destroyBeans(); // 重置ApplicationContext内部active的标志位 cancelRefresh(ex); // 向调用者抛出异常 throw ex; } finally { // 重置Spring核心内的缓存,由于咱们可能再也不须要单例bean相关的元数据 resetCommonCaches(); } } }
阅读完以后咱们重点关注obtainFreshBeanFactory()、finishBeanFactoryInitialization(beanFactory)这两个方法,由于实质上整个IOC的流程都在这两个方法当中,其余的方法一部分是Spring预留给用户的自定义操做如BeanFactory的后置处理器和Bean后置处理器,一部分是关键启动事件的发布和监听操做,一部分是关于AOP的操做。
首先,先从obtainFreshBeanFactory()开始提及。
在getBeanFactory()方法以前,先调用refreshBeanFactory()方法进行刷新。咱们先说明一下,getBeanFactory()很是简单,默认实现只是将上一步刷新成功好构建好的Bean工厂进行返回。返回出去的Bean工厂已经加载好Bean定义了。因此在refreshBeanFactory()这个方法中已经包含了第一步读取xml文件构建DOM对象和第二步解析DOM中的元素生成Bean定义进行保存。记住,这里仅仅是保存好Bean定义,此时并未涉及Bean的实例化。
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { refreshBeanFactory(); ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (logger.isDebugEnabled()) { logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory); } return beanFactory; }
进入refreshBeanFactory()方法中
protected final void refreshBeanFactory() throws BeansException { // 若是当前ApplicationContext中已存在FactoryBean的话进行销毁 if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try { // 先生成一个BeanFactory DefaultListableBeanFactory beanFactory = createBeanFactory(); // 设置序列化 beanFactory.setSerializationId(getId()); // 设置是否能够覆盖Bean定义和是否能够循环依赖,具体我就不解释了 customizeBeanFactory(beanFactory); // 加载Bean定义到Factory当中去 // 重点! loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } }
接下来,进入核心方法loadBeanDefinitions(beanFactory)中,参数是刚建立的beanFactory
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException { // 根据传入的beanfactory建立一个xml读取器 XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); // 设置bean定义读取器的相关资源加载环境 beanDefinitionReader.setEnvironment(this.getEnvironment()); beanDefinitionReader.setResourceLoader(this); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); // 这个方法让子类自定义读取器Reader的初始化 initBeanDefinitionReader(beanDefinitionReader); // 接着开始实际加载Bean定义 loadBeanDefinitions(beanDefinitionReader); }
进入loadBeanDefinitions(beanDefinitionReader)方法中,参数是刚刚建立好的Reader读取器。
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException { // 若是有已经生成好的Resouce实例的话就直接进行解析。 // 默认的实现是返回null,由子类自行实现。 Resource[] configResources = getConfigResources(); if (configResources != null) { reader.loadBeanDefinitions(configResources); } // 没有Resouces的话就进行路径解析。 String[] configLocations = getConfigLocations(); if (configLocations != null) { reader.loadBeanDefinitions(configLocations); } }
咱们进入reader.loadBeanDefinitions(configLocations)方法中,这里面方法调用有点绕,我这边只简单地描述一下
该方法会根据多个不一样位置的xml文件依次进行处理。
接着会对路径的不一样写法进行不一样处理,例如classpath或者WEB-INF的前缀路径。
根据传入的locations变量生成对应的Resouces。
紧接着进入reader.loadBeanDefinitions(resource)此时参数是Resource。
在通过一层进入loadBeanDefinitions(new EncodedResource(resource))的方法调用中。
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()); } // 经过ThreadLocal实现的当前currentResource 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()); } 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(); } } }
该方法最主要是建立了对应的输入流,并设置好编码。
而后开始调用doLoadBeanDefinitions()方法。
// 内部核心代码就这两句 Document doc = doLoadDocument(inputSource, resource); return registerBeanDefinitions(doc, resource);
在loadDocument()方法中会生成一个DocumentBuilderImpl对象,这个对象会调用parse方法,在parse方法中使用SAX进行解析刚才的输入流包装的InputSource,生成DOM对象返回。
public Document parse(InputSource is) throws SAXException, IOException { if (is == null) { throw new IllegalArgumentException( DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "jaxp-null-input-source", null)); } if (fSchemaValidator != null) { if (fSchemaValidationManager != null) { fSchemaValidationManager.reset(); fUnparsedEntityHandler.reset(); } resetSchemaValidator(); } // 解析xml domParser.parse(is); // 获取刚才解析好的dom Document doc = domParser.getDocument(); domParser.dropDocumentReferences(); return doc; }
// 内部核心代码就这两句 Document doc = doLoadDocument(inputSource, resource); return registerBeanDefinitions(doc, resource);
咱们再回到刚刚讲到的这两句核心代码,第一句获取DOM对象后,紧接着第二句registerBeanDefinitions(doc, resource)开始了bean定义的注册工做。
进入registerBeanDefinitions(doc, resource)方法中
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { // 生成DOM读取器,这个和刚才的读取器不同,以前的读取器是xml读取器。 BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); // 获取以前的bean定义数量 int countBefore = getRegistry().getBeanDefinitionCount(); // 进入重点 documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); // 用刚刚又建立的bean定义数量 - 以前的bean定义数量 = 刚刚一共建立的bean定义 return getRegistry().getBeanDefinitionCount() - countBefore; }
进入documentReader.registerBeanDefinitions(doc, createReaderContext(resource))方法。
方法内读取文档的root元素。
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; // 生成Bean定义解析类 this.delegate = createDelegate(getReaderContext(), root, parent); // 若是是xml文档中的namespace,进行相应处理 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)) { if (logger.isInfoEnabled()) { logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec + "] not matching: " + getReaderContext().getResource()); } return; } } } // spring预留给子类的拓展性方法 preProcessXml(root); // 重点 // 开始解析Bean定义 parseBeanDefinitions(root, this.delegate); // spring预留给子类的拓展性方法 postProcessXml(root); this.delegate = parent; }
进入parseBeanDefinitions(root, this.delegate)。将以前的文档对象和bean定义解析类做为参数传入。
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 { // 非默认命名空间的,进行自定义解析,命名空间就是xml文档头内的xmlns,用来定义标签。 delegate.parseCustomElement(root); } }
进入到parseDefaultElement(ele, delegate)当中,会发现其实对四种标签进行分别的解析。
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)) { // 分析Bean标签 processBeanDefinition(ele, delegate); } else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) { // recurse doRegisterBeanDefinitions(ele); } }
咱们主要分析Bean元素标签的解析,进入processBeanDefinition(ele, delegate)方法中最内层。
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) { // 获取bean标签内的id String id = ele.getAttribute(ID_ATTRIBUTE); // 获取bean标签内的name 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)); } // 当没有设置id的时候 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"); } } // 检查beanName是否惟一 if (containingBean == null) { checkNameUniqueness(beanName, aliases, ele); } // 内部作了Bean标签的解析工做 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; }
将解析好的Bean定义并附加别名数组填入new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray)中进行返回。而后调用如下这个方法。
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry())
最主要的操做就是将刚才解析好的Bean定义放入beanDefinitionMap中去。
咱们回到最开始的refresh方法中,在finishBeanFactoryInitialization(beanFactory)方法中,开始实例化非懒加载的Bean对象。咱们跟着调用链进入到preInstantiateSingletons()方法中
@Override public void preInstantiateSingletons() throws BeansException { if (this.logger.isDebugEnabled()) { this.logger.debug("Pre-instantiating singletons in " + this); } // 将以前作好的bean定义名列表拷贝放进beanNames中,而后开始遍历 List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames); // 触发全部非懒加载的单例Bean实例化 for (String beanName : beanNames) { RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); // 若是非抽象而且是单例和非懒加载的话 if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { // 检测是不是工厂方法Bean。 建立Bean的不一样方式,读者可自行百度。 if (isFactoryBean(beanName)) { final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName); boolean isEagerInit; if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() { @Override public Boolean run() { return ((SmartFactoryBean<?>) factory).isEagerInit(); } }, getAccessControlContext()); } else { isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factory).isEagerInit()); } if (isEagerInit) { getBean(beanName); } } else { getBean(beanName); } } } // 关于实例化以后作的自定义操做代码省略.... }
在该方法中根据Bean实例是经过工厂方法实例仍是普通实例化,最主要的方法仍是getBean(beanName)方法。咱们继续分析普通实例化的过程。进入getBean()方法当中doGetBean()方法,发现方法参数doGetBean(name, null, null, false)后三个参数所有为null,它就是整个IOC中的核心代码。
代码中先经过实例化Bean,实例化好以后再判断该Bean所需的依赖,并递归调用进行实例化bean,成功后整个IOC的核心流程也就完成了。
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 { // 若是当前Bean正在建立中的话就直接失败, // 能够陷入了循环引用。 if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } // 检测Bean定义是否出如今父Bean工厂 BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { // 父工厂不为null而且当前不包含这个Bean定义时 // 从父工厂去返回Bean 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 { // 将子Bean定义与父Bean定义进行整合 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); // 整合后若是发现是抽象类不能实例 抛出异常 checkMergedBeanDefinition(mbd, beanName, args); // 获取Bean定义所需的依赖并逐一初始化填充 String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dep : dependsOn) { // 判断是否循环依赖 if (isDependent(beanName, dep)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } // 注册依赖的Bean registerDependentBean(dep, beanName); try { // 递归调用生成所需依赖的Bean getBean(dep); } catch (NoSuchBeanDefinitionException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", ex); } } } // 若是是单例的话 if (mbd.isSingleton()) { 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 name '" + 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; } } // 检测实例Bean的类型和所需类型是否一致 if (requiredType != null && bean != null && !requiredType.isInstance(bean)) { 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; }
文章篇幅有限,IOC整个的建立过程仍是比较冗长的,但愿读者看完文章对IOC的建立过程有一个主干脉络的思路以后仍是须要翻开源码进行解读,其实阅读源码并不难,由于Spring的代码注释都挺健全,若是遇到不清楚的稍微google一下就知道了。建议读者本身试着一步一步的分析IOC过程的源码。