本文共 24608 字,大约阅读时间需要 82 分钟。
1、示例POJO类
用户类User,其中包含一个狗的引用
package org.springframework.cn.shu.edu.pojo;public class User { String username; String password; Dog dog; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Dog getDog() { return dog; } public void setDog(Dog dog) { this.dog = dog; }}
狗类
package org.springframework.cn.shu.edu.pojo;public class Dog { String name; public String getName() { return name; } public void setName(String name) { this.name = name; }}
2、工程结构
3、spring配置文件beans.xml
其中配置了一个Dog类的对象,一个User类的对象。
4、测试代码
import org.springframework.beans.factory.support.DefaultListableBeanFactory;import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;import org.springframework.cn.shu.edu.pojo.User;import org.springframework.core.io.ClassPathResource;import org.springframework.core.io.Resource;public class Test1 { public static void main(String[] args) { Resource res = new ClassPathResource("beans.xml"); DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory); reader.loadBeanDefinitions(res); User chenjie = factory.getBean("chenjie", User.class); System.out.println(chenjie.getUsername()); User chenjie2 = factory.getBean("chenjie", User.class); System.out.println(chenjie2.getDog().getName()); }}
其中,首先定义了一个资源,指定从classpath下加载beans.xml文件,然后新建了一个DefaultListableBeanFactory的工厂对象,然后新建了一个XmlBeanDefinitionReader的Xml类定义读取器,接着使用该读取器加载bean定义。
随后便可以使用创建的工厂了,我们调用两次getBean。
首先观看输出:
可以看到User类中的Dog类对象的引用两次都没有找到,而User类第一次没有找到,第二次找到了。我们将分析整个过程。
5、
Resource res = new ClassPathResource("beans.xml");
此句新建了一个ClassPathResource对象,用beans.xml作为参数。看看ClassPathResource的类图
Resource是Spring用来封装IO操作的类。在这里我们的BeanDefinition信息是以xml文件形式存在的。
这句代码首先调用了一个参数的构造函数,参数为bean定义的配置文件的路径
public ClassPathResource(String path) { this(path, (ClassLoader) null); }
可以看到它又调用了两个参数的构造函数,其中第二个参数为ClassLoader类型,这里由于此前没有指定ClassLoader是谁,因此设置为空。
再看看两个参数的构造函数
public ClassPathResource(String path, ClassLoader classLoader) { //判空 Assert.notNull(path, "Path must not be null"); //清洗路径 String pathToUse = StringUtils.cleanPath(path); if (pathToUse.startsWith("/")) { pathToUse = pathToUse.substring(1); } this.path = pathToUse; //得到classLoader this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader()); }
首先由于必须给定配置文件的路径,因此使用了断言来判空。
然后使用StringUtils工具类的cleanPath方法进行路径的整理。
public static String cleanPath(String path) { if (path == null) { return null; } String pathToUse = replace(path, WINDOWS_FOLDER_SEPARATOR, FOLDER_SEPARATOR); // Strip prefix from path to analyze, to not treat it as part of the // first path element. This is necessary to correctly parse paths like // "file:core/../core/io/Resource.class", where the ".." should just // strip the first "core" directory while keeping the "file:" prefix. int prefixIndex = pathToUse.indexOf(":"); String prefix = ""; if (prefixIndex != -1) { prefix = pathToUse.substring(0, prefixIndex + 1); pathToUse = pathToUse.substring(prefixIndex + 1); } if (pathToUse.startsWith(FOLDER_SEPARATOR)) { prefix = prefix + FOLDER_SEPARATOR; pathToUse = pathToUse.substring(1); } String[] pathArray = delimitedListToStringArray(pathToUse, FOLDER_SEPARATOR); ListpathElements = new LinkedList (); int tops = 0; for (int i = pathArray.length - 1; i >= 0; i--) { String element = pathArray[i]; if (CURRENT_PATH.equals(element)) { // Points to current directory - drop it. } else if (TOP_PATH.equals(element)) { // Registering top path found. tops++; } else { if (tops > 0) { // Merging path element with element corresponding to top path. tops--; } else { // Normal path element found. pathElements.add(0, element); } } } // Remaining top paths need to be retained. for (int i = 0; i < tops; i++) { pathElements.add(0, TOP_PATH); } return prefix + collectionToDelimitedString(pathElements, FOLDER_SEPARATOR); }
整理完成以后,判断路径是否以/开头,如果是/开头,则表示是相对于classpath是根目录,所以用/后面的作为路径。
然后判断classloader是否为空,如果传入的不为空则使用之,如果为空,则调用ClassUtils.getDefaultClassLoader()来获取默认的ClassLoader,其方法如下。
public static ClassLoader getDefaultClassLoader() { ClassLoader cl = null; try { cl = Thread.currentThread().getContextClassLoader(); } catch (Throwable ex) { // Cannot access thread context ClassLoader - falling back to system class loader... } if (cl == null) { // No thread context class loader -> use class loader of this class. cl = ClassUtils.class.getClassLoader(); } return cl; }
首先尝试得到当前线程的上下文的ClassLoader,如果获取失败会抛出异常,cl为空,则会获取ClassUtil类对象的ClassLoader并返回。
6、
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
首先看看DefaultListableBeanFactory的类图。
可以看到是一个相对复杂的继承关系。
首先调用DefaultListableBeanFactory类的无参构造函数。
/** * Create a new DefaultListableBeanFactory. */ public DefaultListableBeanFactory() { super(); logger.info("初始化DefaultListableBeanFactory完成"); }
可以看到什么都没有做,只是调用了父类的无参构造函数。我们来看看它的父类AbstractAutowireCapableBeanFactory的无参构造函数。
/** * Create a new AbstractAutowireCapableBeanFactory. */ public AbstractAutowireCapableBeanFactory() { super(); logger.info("初始化AbstractAutowireCapableBeanFactory()完成"); ignoreDependencyInterface(BeanNameAware.class); ignoreDependencyInterface(BeanFactoryAware.class); ignoreDependencyInterface(BeanClassLoaderAware.class); }
可以看到其调用了父类的无参构造函数,接着调用了三次ignoreDependencyInterface方法,该方法其作用是指定自动装配(autowiring)的时候忽略的接口。这里我们先不做讨论。
我们来看看其调用的父类AbstractBeanFactory的无参构造函数
/** * Create a new AbstractBeanFactory. */ public AbstractBeanFactory() { logger.info("初始化AbstractBeanFactory()完成"); }
其中什么都没有做。到这里没有再显式地调用父类的构造函数,事实上,当我们再看AbstractBeanFactory的父类FactoryBeanRegistrySupport,FactoryBeanRegistrySupport的父类DefaultSingletonBeanRegistry,DefaultSingletonBeanRegistry的父类SimpleAliasRegistry的源码会发现其都没有写构造方法,也就是说其都是默认的空的无参构造函数。
7、
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
这里新建一个XmlBeanDefinitionReader对象,并以此前创建的DefaultListableBeanFactory的对象factory作为参数。
public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) { super(registry); logger.info("初始化XmlBeanDefinitionReader()完成"); }
再看其构造器,发现需要的参数只需要实现BeanDefinitionRegistry 接口即可,观察类图或者查看源码可知DefaultListableBeanFactory实现了BeanDefinitionRegistry接口
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {}
该接口中有bean定义数量和bean定义名称两个属性,有注册bean定义、移除bean定义,得到bean定义、判断是否包含bean定义、bean名称是否在使用等方法。
XmlBeanDefinitionReader调用了父类的构造器如下:
protected AbstractBeanDefinitionReader(BeanDefinitionRegistry registry) { Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); this.registry = registry; // Determine ResourceLoader to use. if (this.registry instanceof ResourceLoader) { logger.info("this.registry instanceof ResourceLoader" ); this.resourceLoader = (ResourceLoader) this.registry; } else { logger.info("this.registry is not instanceof ResourceLoader" ); this.resourceLoader = new PathMatchingResourcePatternResolver(); } }
首先进行必要的判空和赋值,然后判断传入的参数(这个registry对象参数肯定实现了BeanDefinitionRegistry ,但是否实现了ResourceLoader未知)是否实现了ResourceLoader。
我们这里传入的DefaultListableBeanFactory对象没有实现这个接口,因此在else里面,会新建一个PathMatchingResourcePatternResolver对象。
ResourceLoader提供 classpath下单资源文件的载入,而ResourcePatternResolver提供了多资源文件的载入。ResourcePatternResolver有一个实现类:PathMatchingResourcePatternResolver
我们这里新建了一个PathMatchingResourcePatternResolver对象。我们先不深入。
7、
reader.loadBeanDefinitions(res);
这里使用了XmlBeanDefinitionReader类的loadBeanDefinitions方法加载Resource类的对象res。
/** * Load bean definitions from the specified XML file. * @param resource the resource descriptor for the XML file * @return the number of bean definitions found * @throws BeanDefinitionStoreException in case of loading or parsing errors */ public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException { logger.info("进入loadBeanDefinitions(Resource resource)"); return loadBeanDefinitions(new EncodedResource(resource)); }
这里首先将resource进行encode,作用是进行编码。然后我们看看loadBeanDefinitions的具体实现。
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException { logger.info("进入loadBeanDefinitions(EncodedResource encodedResource)"); Assert.notNull(encodedResource, "EncodedResource must not be null"); if (logger.isInfoEnabled()) { logger.info("Loading XML bean definitions from " + encodedResource.getResource()); } SetcurrentResources = this.resourcesCurrentlyBeingLoaded.get(); if (currentResources == null) { currentResources = new HashSet (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(); } } }
进行必要的判空后,首先使用
SetcurrentResources = this.resourcesCurrentlyBeingLoaded.get();
XmlBeanDefinitionReader内部维护了一个resourcesCurrentlyBeingLoaded变量,用于保存最近被加载的资源。private final ThreadLocal> resourcesCurrentlyBeingLoaded = new NamedThreadLocal >("XML bean definition resources currently being loaded");
如果为空,则进行必要的初始化。
然后将传入的参数加入currentResources中,紧接着得到资源里面的输入流(public interface Resource extends InputStreamSource):
InputStream inputStream = encodedResource.getResource().getInputStream();
然后将输入流封装成了org.xml.sax库的InputSource对象,这里完成对xml的解析的加载过程。然后进行编码设置。
接着调用了doLoadBeanDefinitions(inputSource, encodedResource.getResource());方法。
做完以后关闭流,最后将传入的资源从最近被加载的资源中删除。
我们来看看doLoadBeanDefinitions方法的实现。
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException { try { int validationMode = getValidationModeForResource(resource); Document doc = this.documentLoader.loadDocument( inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware()); return registerBeanDefinitions(doc, resource); }//....}
其中涉及validationMode验证模式,可以参考https://blog.csdn.net/nangongyanya/article/details/53887467
然后使用this.documentLoader.loadDocument方法来加载xml文档。documentLoader是DefaultDocumentLoader类的对象。
private DocumentLoader documentLoader = new DefaultDocumentLoader();
让我们来看看DefaultDocumentLoader类的loadDocument方法。
public Document loadDocument(InputSource inputSource, EntityResolver entityResolver, ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception { DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware); if (logger.isDebugEnabled()) { logger.debug("Using JAXP provider [" + factory.getClass().getName() + "]"); } DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler); return builder.parse(inputSource); }
它有几个参数,分别是输入源inputSource,实体解析器entityResolver,错误处理器errorHandler,XML验证模式validationMode,namespaceAware。最终落实到DocumentBuilder的parse方法。
接着调用registerBeanDefinitions(doc, resource);
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { // Read document based on new BeanDefinitionDocumentReader SPI. BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); int countBefore = getRegistry().getBeanDefinitionCount(); documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); return getRegistry().getBeanDefinitionCount() - countBefore; }
其中createBeanDefinitionDocumentReader方法主要新建了一个BeanDefinitionDocumentReader 接口的实现类DefaultBeanDefinitionDocumentReader然后调用其registerBeanDefinitions方法
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) { this.readerContext = readerContext; logger.info("---->Loading bean definitions at " + DefaultBeanDefinitionDocumentReader.class.getSimpleName()); Element root = doc.getDocumentElement(); logger.info("--->root:" + root.getTagName()); BeanDefinitionParserDelegate delegate = createHelper(readerContext, root); preProcessXml(root); parseBeanDefinitions(root, delegate); postProcessXml(root); }
其中root代表了xml文档的根元素,可以增加打印语句看看:
从输出可以看到其根元素为<beans></beans>
接着Bean定义解析代理类BeanDefinitionParserDelegate的对象,由它解析根元素中的内容,对于根元素前和跟元素后的内容,则由preProcessXml和postProcessXml两个方法完成,目前为空实现。我们来看看parseBeanDefinitions方法。
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); } }
首先判断是否是默认的命名空间,如果是,则执行parseDefaultElement,否则执行parseCustomElement。
我们这里是使用的默认的命名空间,因此接着调用getChildNodes方法获得<beans></beans>下面的子节点,也就是<bean></bean>。
然后对于每个子节点,根据当前是否是默认命名空间来调用不同方法解析。
我们这里先只看parseDefaultElement。
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)) { processBeanDefinition(ele, delegate); } }
这里分了3种情况,分别是节点标签名对应import alias 和bean的情况。
它们分别处理<import/> <alias/>和<bean/>
我们这里只涉及bean的解析。来看看。
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { /*** * BeanDefinitionHolder是BeanDefinition对象的封装类,封装了BeanDefinition,Bean的名字和别名。用它来完成向IoC容器注册。 * 得到这个BeanDefinition实际上就意味着获得了BeanDefinition,是通过BeanDefinitionParserDelegate对XML元素的信息按照 * Spring的Bean规则进行解析得到的 */ BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); if (bdHolder != null) { bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); try { // 这里是向IoC容器注册解析得到的BeanDefinition的地方。 BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); } catch (BeanDefinitionStoreException ex) { getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, ex); } // 发送注册事件 getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder)); } }
BeanDefinitionHolder是BeanDefinition的封装。
而BeanDefinition可以看成是<bean>定义的抽象。
可以看到其中包含关于类名、原型、延迟加载、单例、依赖的方法。
具体的加载过程由BeanDefinitionParserDelegate对XML元素的信息按照Spring的Bean规则进行解析得到的,入口是
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean){}
其中会调用parseBeanDefinitionElement方法。
public AbstractBeanDefinition parseBeanDefinitionElement( Element ele, String beanName, BeanDefinition containingBean) { logger.info("\tgo into parseBeanDefinitionElement of beanName :" + beanName); this.parseState.push(new BeanEntry(beanName)); String className = null; if (ele.hasAttribute(CLASS_ATTRIBUTE)) { className = ele.getAttribute(CLASS_ATTRIBUTE).trim(); logger.info("\tclass =" + className); } try { String parent = null; //如果元素有parent属性 if (ele.hasAttribute(PARENT_ATTRIBUTE)) { //得到parent节点 parent = ele.getAttribute(PARENT_ATTRIBUTE); } //根据parent创建AbstractBeanDefinition AbstractBeanDefinition bd = createBeanDefinition(className, parent); //解析bean定义 parseBeanDefinitionAttributes(ele, beanName, containingBean, bd); //为bean定义设置描述 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; } catch (ClassNotFoundException ex) { error("Bean class [" + className + "] not found", ele, ex); } catch (NoClassDefFoundError err) { error("Class that bean class [" + className + "] depends on not found", ele, err); } catch (Throwable ex) { error("Unexpected failure during bean definition parsing", ele, ex); } finally { this.parseState.pop(); } return null; }
其中createBeanDefinition创建一个BeanDefinition的实现GenericBeanDefinition。然后调用parseConstructorArgElements、parsePropertyElements等解析构造器参数,解析属性元素等。
createBeanDefinition中直接使用BeanDefinitionReaderUtils.createBeanDefinition创建bean。
public static AbstractBeanDefinition createBeanDefinition( String parentName, String className, ClassLoader classLoader) throws ClassNotFoundException { GenericBeanDefinition bd = new GenericBeanDefinition(); bd.setParentName(parentName); if (className != null) { if (classLoader != null) { bd.setBeanClass(ClassUtils.forName(className, classLoader)); } else { bd.setBeanClassName(className); } } return bd; }
其中使用了ClassUtils加载类的定义,然后为BeanDefinition设置了bean的class属性。
parsePropertyElements中循环调用了多次parsePropertyElement来处理每个property
与XML中定义一致。
然后回到:DefaultBeanDefinitionDocumentReader
解析bean定义后,使用如下方法注册bean定义,这里的getReaderContext().getRegistry()就是最开始新建的工厂对象DefaultListableBeanFactory。
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
主要代码如下,即调用registerBeanDefinition方法。
该方法主要是往一个并发HashMap中写入刚刚注册得到的bean定义
private final MapbeanDefinitionMap = new ConcurrentHashMap ();
由此,便将bean名字到bean定义的映射保存在了DefaultListableBeanFactory中。
8、
User chenjie = factory.getBean("chenjie", User.class);
这里调用了DefaultListableBeanFactory的getBean方法,但该方法是从父类AbstractBeanFactory继承而来。
publicT getBean(String name, Class requiredType) throws BeansException { logger.info("AbstractBeanFactory getBean,name=" + name + ",requiredType=" + requiredType); return doGetBean(name, requiredType, null, false); }
直接调用doGetBean
protectedT doGetBean( final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException { logger.info("AbstractBeanFactory doGetBean,name=" + name + ",requiredType=" + requiredType); final String beanName = transformedBeanName(name); logger.info("transformedBeanName, beanName=" + beanName); Object bean; // Eagerly check singleton cache for manually registered singletons. //先从缓存中去取,处理已经被创建过的单件模式的bean,对这种bean的请求不需要重复地创建 Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { logger.info("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 + "'"); } } /*** * 这里的getObjectForBeanInstance完成的是FactoryBean的相关处理, * 以取得FactoryBean的生产结果,BeanFactory和FactoryBean的区别 * 会在这个过程中详细地分析 */ bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { logger.info("sharedInstance == null || args != null"); // 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. /** * 这里对IoC容器里的BeanDefinition是否存在进行检查,检查是否能在当前的BeanFactory中取到我们需要的bean。 * 如果在当前的工厂中取不到,则到双亲BeanFactory中去取; * 如果当前的双亲工厂取不到,那就顺着双亲BeanFactory链一直向上查找 */ 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); } //这里根据bean的名字取得BeanDefinition final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); // Guarantee initialization of beans that the current bean depends on. /*** * 取当前bean的所有依赖bean,这样会触发getBean的递归调用,直至取到一个没有任何依赖的bean为止。 */ String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dependsOnBean : dependsOn) { getBean(dependsOnBean); registerDependentBean(dependsOnBean, beanName); } } // Create bean instance. /*** * 这里创建Singleton bean的实例,通过调用crateBean方法,这里有个回调函数getObject, * 会在getSingleton中调用ObjectFactory的createBean */ if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, new ObjectFactory() { 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); } //这里是创建prototype bean的地方 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() { 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. /*** * 这里对创建出来的bean进行类型检查,如果没有问题,就返回这个新创建出来的bean, * 这个bean已经是包含了依赖关系的bean */ 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; }
总结: