创建日期:2016.08.06

修改日期:2016.08.07 - 2016.08.12

交流QQ:992591601

参考书籍:《spring源码深度解析》、《spring技术内幕》

参考文章:http://www.cnblogs.com/xing901022/p/4178963.html

http://www.myexception.cn/program/1031276.html

http://blog.csdn.net/qian_348840260/article/details/7994936

一、搭建工程,运行简单示例:

  1. @Test
  2. public void testSimpleLoad() {
  3. BeanFactory bf = new XmlBeanFactory(new ClassPathResource ("beans.xml"));
  4. Person bean = (Person) bf.getBean("person");
  5. bean.info();
  6. }

其余代码我就不贴了,很基本。要说明一点,要看spring源码的话,需要在导入的spring jar包附上额外的源码包,eclipse可以配置:

二、这个工程的test程序只有短短几行,但背后的spring代码却是繁多复杂的。

BeanFactory bf = new XmlBeanFactory(new ClassPathResource ("beans.xml"));
Person bean = (Person) bf.getBean("person");

这两句的逻辑看起来很简单,首先依据xml文件创建工厂类,再通过工厂类从容器获取bean。在这个过程中用ClassPathResource类来对配置文件作一个包装,然后作为XmlBeanFactory构造函数的参数。

BeanFactory是一个接口。

先来看ClassPathResource类。经过代码阅读,可以总结UML图:

可以清晰看得出来,spring的设计者在这里应用了一个著名设计模式:策略模式。简单些讲,就是面向接口编程的一种思路。在这里UrlResource和ClassPathResource都实现了Resource接口,是Resource接口的两种实现策略。

我们首先看Resource接口,这是最基础的定义:

  1. public interface Resource extends InputStreamSource {
  2. boolean exists();
  3. boolean isReadable();
  4. boolean isOpen();
  5. URL getURL() throws IOException;
  6. URI getURI() throws IOException;
  7. File getFile() throws IOException;
  8. long contentLength() throws IOException;
  9. long lastModified() throws IOException;
  10. Resource createRelative(String relativePath) throws IOException;
  11. String getFilename();
  12. String getDescription();
  13. }

该接口定义了一些很基本的方法。都是一些很必要的get操作。具体实现自然要交给两个策略来实现:UrlResource和ClassPathResource。另外,值得一提的是该接口还继承了一个接口InputStreamSource。该接口只定义了一个方法:

InputStream getInputStream() throws IOException;    是用来获取java I/O的。

抽象类AbstractResource是接口与实现策略之间的中间层。实现了Resource接口的所有方法。在此基础上,策略类继承该抽象类之后,就只需提供自己特有的方法即可了。然而很多方法例如getURL都要在策略类里重写的,因为url这种数据还是要具体实例化时才能得到。

具体实现细节不多说,总结一下,就是spring的资源文件通过Resource接口的实现类来包装。而这些实现类与Resource接口的关系是一种策略模式。

接下来看XmlBeanFactory类的代码:

  1. public class XmlBeanFactory extends DefaultListableBeanFactory {
  2. private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
  3. /**
  4. * Create a new XmlBeanFactory with the given resource,
  5. * which must be parsable using DOM.
  6. * @param resource XML resource to load bean definitions from
  7. * @throws BeansException in case of loading or parsing errors
  8. */
  9. public XmlBeanFactory(Resource resource) throws BeansException {
  10. this(resource, null);
  11. }
  12. /**
  13. * Create a new XmlBeanFactory with the given input stream,
  14. * which must be parsable using DOM.
  15. * @param resource XML resource to load bean definitions from
  16. * @param parentBeanFactory parent bean factory
  17. * @throws BeansException in case of loading or parsing errors
  18. */
  19. public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
  20. super(parentBeanFactory);
  21. this.reader.loadBeanDefinitions(resource);
  22. }
  23. }

XmlBeanFactory将Resource作为构造函数参数。这里XmlBeanDefinitionReader是关键,用来根据Resource来loadBeanDefinitions。这是XmlBeanFactory对基类DefaultListableBeanFactory的添加。

EncodeResource是对resource的封装,采用装饰者模式。主要增加了编码的信息。在很多时候,虽然两个类具有一定继承关系,但采用组合代替继承是更好的设计

  1. public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
  2. Assert.notNull(encodedResource, "EncodedResource must not be null");
  3. if (logger.isInfoEnabled()) {
  4. logger.info("Loading XML bean definitions from " + encodedResource.getResource());
  5. }
  6. Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
  7. if (currentResources == null) {
  8. currentResources = new HashSet<EncodedResource>(4);
  9. this.resourcesCurrentlyBeingLoaded.set(currentResources);
  10. }
  11. if (!currentResources.add(encodedResource)) {
  12. throw new BeanDefinitionStoreException(
  13. "Detected cyclic loading of " + encodedResource + " - check your import definitions!");
  14. }
  15. try {
  16. InputStream inputStream = encodedResource.getResource().getInputStream();
  17. try {
  18. InputSource inputSource = new InputSource(inputStream);
  19. if (encodedResource.getEncoding() != null) {
  20. inputSource.setEncoding(encodedResource.getEncoding());
  21. }
  22. return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
  23. }
  24. finally {
  25. inputStream.close();
  26. }
  27. }
  28. catch (IOException ex) {
  29. throw new BeanDefinitionStoreException(
  30. "IOException parsing XML document from " + encodedResource.getResource(), ex);
  31. }
  32. finally {
  33. currentResources.remove(encodedResource);
  34. if (currentResources.isEmpty()) {
  35. this.resourcesCurrentlyBeingLoaded.remove();
  36. }
  37. }
  38. }

该方法作用是将XML文件转化为BeanDefinitions。

这段代码意思是:

1,获取线程局部变量resourcesCurrentlyBeingLoaded,  final ThreadLocal<Set<EncodedResource>>类型。

将当前要加载的Source,放入final ThreadLocal<Set<EncodedResource>>,若无法放入则抛出异常。

2,核心,真正的去加载Resource:

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();
}

3,将加载过的Resource从resourcesCurrentlyBeingLoaded删除。

这里面1和3涉及多线程操作,这里面了解下java的ThreadLocal:ThreadLocal是指线程类的局部变量,他可以保证每一个线程都保有一份自己的局部变量的副本,线程之间不会对别的线程的ThreadLocal产生影响。

从代码上看,1和3的意义就是用ThreadLocal标注当前线程正在加载的Resource。

2是核心部分,调用doLoadBeanDefinitions(InputSource inputSource, Resource resource)方法

  1. protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
  2. throws BeanDefinitionStoreException {
  3. try {
  4. int validationMode = getValidationModeForResource(resource);
  5. Document doc = this.documentLoader.loadDocument(
  6. inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware());
  7. return registerBeanDefinitions(doc, resource);
  8. }
  9. catch (BeanDefinitionStoreException ex) {
  10. throw ex;
  11. }
  12. catch (SAXParseException ex) {
  13. throw new XmlBeanDefinitionStoreException(resource.getDescription(),
  14. "Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);
  15. }
  16. catch (SAXException ex) {
  17. throw new XmlBeanDefinitionStoreException(resource.getDescription(),
  18. "XML document from " + resource + " is invalid", ex);
  19. }
  20. catch (ParserConfigurationException ex) {
  21. throw new BeanDefinitionStoreException(resource.getDescription(),
  22. "Parser configuration exception parsing XML from " + resource, ex);
  23. }
  24. catch (IOException ex) {
  25. throw new BeanDefinitionStoreException(resource.getDescription(),
  26. "IOException parsing XML document from " + resource, ex);
  27. }
  28. catch (Throwable ex) {
  29. throw new BeanDefinitionStoreException(resource.getDescription(),
  30. "Unexpected exception parsing XML document from " + resource, ex);
  31. }
  32. }

关键是这三句:

int validationMode = getValidationModeForResource(resource);
Document doc = this.documentLoader.loadDocument(
                                                  inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware());
return registerBeanDefinitions(doc, resource);

继续看loadDocument方法代码:

  1. public Document loadDocument(InputSource inputSource, EntityResolver entityResolver,
  2. ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {
  3. DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware);
  4. if (logger.isDebugEnabled()) {
  5. logger.debug("Using JAXP provider [" + factory.getClass().getName() + "]");
  6. }
  7. DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler);
  8. return builder.parse(inputSource);
  9. }

关于参数,entityResolver,解释起来有些麻烦,直接引用《spring源码深度解析》一书的文字吧:

int validationMode = getValidationModeForResource(resource); 这句是获取对应资源的验证方式。两种验证模式:DTD、XSD

这里DocumentBuilder的创建方式体现了工厂模式。具体创建是靠DocumentBuilderFactory factory作为参数。而factory的创建是方法protected DocumentBuilderFactory createDocumentBuilderFactory(int validationMode, boolean namespaceAware)

DocumentBuilderFactory和DocumentBuilder都是抽象类,真正实例化的是对抽象类的实现类。

不管怎么样,它return builder.parse(inputSource)   return的是一个Document类。

Document接口注释:

* The <code>Document</code> interface represents the entire HTML or XML
 * document. Conceptually, it is the root of the document tree, and provides
 * the primary access to the document's data.

而Document接口又是继承了Node接口。

loadDocument方法就是将文件转化为Document类的过程。

继续看代码:

  1. public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
  2. // Read document based on new BeanDefinitionDocumentReader SPI.
  3. BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
  4. int countBefore = getRegistry().getBeanDefinitionCount();
  5. documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
  6. return getRegistry().getBeanDefinitionCount() - countBefore;
  7. }
  1. public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
  2. this.readerContext = readerContext;
  3. logger.debug("Loading bean definitions");
  4. Element root = doc.getDocumentElement();
  5. BeanDefinitionParserDelegate delegate = createHelper(readerContext, root);
  6. preProcessXml(root);
  7. parseBeanDefinitions(root, delegate);
  8. postProcessXml(root);
  9. }
  10. protected BeanDefinitionParserDelegate createHelper(XmlReaderContext readerContext, Element root) {
  11. BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext);
  12. delegate.initDefaults(root);
  13. return delegate;
  14. }

Element root = doc.getDocumentElement();获取根节点Element。

/**
 * The <code>Element</code> interface represents an element in an HTML or XML
 * document. Elements may have attributes associated with them; since the
 * <code>Element</code> interface inherits from <code>Node</code>, the
 * generic <code>Node</code> interface attribute <code>attributes</code> may
 * be used to retrieve the set of all attributes for an element. There are
 * methods on the <code>Element</code> interface to retrieve either an
 * <code>Attr</code> object by name or an attribute value by name. In XML,
 * where an attribute value may contain entity references, an
 * <code>Attr</code> object should be retrieved to examine the possibly
 * fairly complex sub-tree representing the attribute value. On the other
 * hand, in HTML, where all attributes have simple string values, methods to
 * directly access an attribute value can safely be used as a convenience.
 * <p ><b>Note:</b> In DOM Level 2, the method <code>normalize</code> is
 * inherited from the <code>Node</code> interface where it was moved.
 * <p>See also the <a href='http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407'>Document Object Model (DOM) Level 3 Core Specification</a>.
 */
public interface Element extends Node{……}

而这里的BeanDefinitionParserDelegate delegate是用来做转换工作。

spring源码的阅读工作就是一层套一层……然而并不难搞懂

理解下面的代码必须要提及spring XML配置里有两种bean的声明,一种是默认的<bean id = "test" class = "test.TestBean"/>另一种就是自定义的:<tx:annotation-driven/>:

  1. /**
  2. * Parse the elements at the root level in the document:
  3. * "import", "alias", "bean".
  4. * @param root the DOM root element of the document
  5. */
  6. protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
  7. //如果是默认方式声明bean
  8. if (delegate.isDefaultNamespace(root)) {
  9. NodeList nl = root.getChildNodes();
  10. for (int i = 0; i < nl.getLength(); i++) {
  11. Node node = nl.item(i);
  12. if (node instanceof Element) {
  13. Element ele = (Element) node;
  14. if (delegate.isDefaultNamespace(ele)) {
  15. parseDefaultElement(ele, delegate);
  16. }
  17. else {
  18. delegate.parseCustomElement(ele);
  19. }
  20. }
  21. }
  22. }
  23. //自定义方式声明bean
  24. else {
  25. delegate.parseCustomElement(root);
  26. }
  27. }

这里是从根节点,开始转换。

继续看核心操作parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate)方法:

  1. private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
  2. if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
  3. importBeanDefinitionResource(ele);
  4. }
  5. else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
  6. processAliasRegistration(ele);
  7. }
  8. else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
  9. processBeanDefinition(ele, delegate);
  10. }
  11. }

看代码感觉这是在根据节点名称类型选择注册操作,继续看void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate)方法:

  1. /**
  2. * Process the given bean element, parsing the bean definition
  3. * and registering it with the registry.
  4. */
  5. protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
  6. BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
  7. if (bdHolder != null) {
  8. bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
  9. try {
  10. // Register the final decorated instance.
  11. BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
  12. }
  13. catch (BeanDefinitionStoreException ex) {
  14. getReaderContext().error("Failed to register bean definition with name '" +
  15. bdHolder.getBeanName() + "'", ele, ex);
  16. }
  17. // Send registration event.
  18. getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
  19. }
  20. }

这里BeanDefinitionHolder也是采用了装饰者模式。包含了BeanDefinition,添加了:

private final String beanName;

private final String[] aliases;
两个私有final变量。

另外注意BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());这句。

  1. public static void registerBeanDefinition(
  2. BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
  3. throws BeanDefinitionStoreException {
  4. // Register bean definition under primary name.
  5. String beanName = definitionHolder.getBeanName();
  6. registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
  7. // Register aliases for bean name, if any.
  8. String[] aliases = definitionHolder.getAliases();
  9. if (aliases != null) {
  10. for (String aliase : aliases) {
  11. registry.registerAlias(beanName, aliase);
  12. }
  13. }
  14. }

BeanDefinitionRegistry是XMLBeanFactory的基类之一。设置断点跟踪,我们可以发现,进入这个方法,传进来的类实例正是XmlBeanFactory。接下来调用的是XmlBeanFactory类的方法,registerBeanDefinition。方法内部调用的这里是真正的注册的实现:将BeanDefinition添加的,Spring的BeanFactory容器里,一个Map数据结构:

/** Map of bean definition objects, keyed by bean name */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>();

  1. public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
  2. throws BeanDefinitionStoreException {
  3. Assert.hasText(beanName, "Bean name must not be empty");
  4. Assert.notNull(beanDefinition, "BeanDefinition must not be null");
  5. if (beanDefinition instanceof AbstractBeanDefinition) {
  6. try {
  7. ((AbstractBeanDefinition) beanDefinition).validate();
  8. }
  9. catch (BeanDefinitionValidationException ex) {
  10. throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
  11. "Validation of bean definition failed", ex);
  12. }
  13. }
  14. synchronized (this.beanDefinitionMap) {
  15. Object oldBeanDefinition = this.beanDefinitionMap.get(beanName);
  16. if (oldBeanDefinition != null) {
  17. if (!this.allowBeanDefinitionOverriding) {
  18. throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
  19. "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
  20. "': There is already [" + oldBeanDefinition + "] bound.");
  21. }
  22. else {
  23. if (this.logger.isInfoEnabled()) {
  24. this.logger.info("Overriding bean definition for bean '" + beanName +
  25. "': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
  26. }
  27. }
  28. }
  29. else {
  30. this.beanDefinitionNames.add(beanName);
  31. this.frozenBeanDefinitionNames = null;
  32. }
  33. this.beanDefinitionMap.put(beanName, beanDefinition);
  34. resetBeanDefinition(beanName);
  35. }
  36. }

以上所述就是BeanFactory bf = new XmlBeanFactory(new ClassPathResource ("beans.xml"));这句代码背后的故事。

首先,ClassPathResource类封装了资源文件,作为构造函数参数来创建XmlBeanFactory。经过一系列复杂转换将XML文件转换为spring需要的数据结构~ BeanDefinition

对XML的解析和BeanDefinition就介绍到这,介绍的并不够绝对细致,主要是理解大意,另外也是spring源码确实比较繁杂。并且以后有了新的心得还会在这篇文章做修改补充。

接下来这句:Person bean = (Person) bf.getBean("person");

代码的字面意思就是从spring容器里,获取person bean的实例对象。

这里要提到BeanFactory和ApplicationContext的区别:BeanFactory是采取延迟加载,只有当getBean的时候才会去加载、实例化这个对象。ApplicationContext则正相反,它是一次性加载所有bean。

getBean的最终实现是 AbstractBeanFactory的 doGetBean方法

  1. @SuppressWarnings("unchecked")
  2. protected <T> T doGetBean(
  3. final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
  4. throws BeansException {
  5. final String beanName = transformedBeanName(name);
  6. Object bean;
  7. // Eagerly check singleton cache for manually registered singletons.
  8. Object sharedInstance = getSingleton(beanName);
  9. if (sharedInstance != null && args == null) {
  10. if (logger.isDebugEnabled()) {
  11. if (isSingletonCurrentlyInCreation(beanName)) {
  12. logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
  13. "' that is not fully initialized yet - a consequence of a circular reference");
  14. }
  15. else {
  16. logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
  17. }
  18. }
  19. bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
  20. }
  21. else {
  22. // Fail if we're already creating this bean instance:
  23. // We're assumably within a circular reference.
  24. if (isPrototypeCurrentlyInCreation(beanName)) {
  25. throw new BeanCurrentlyInCreationException(beanName);
  26. }
  27. // Check if bean definition exists in this factory.
  28. BeanFactory parentBeanFactory = getParentBeanFactory();
  29. if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
  30. // Not found -> check parent.
  31. String nameToLookup = originalBeanName(name);
  32. if (args != null) {
  33. // Delegation to parent with explicit args.
  34. return (T) parentBeanFactory.getBean(nameToLookup, args);
  35. }
  36. else {
  37. // No args -> delegate to standard getBean method.
  38. return parentBeanFactory.getBean(nameToLookup, requiredType);
  39. }
  40. }
  41. if (!typeCheckOnly) {
  42. markBeanAsCreated(beanName);
  43. }
  44. final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
  45. checkMergedBeanDefinition(mbd, beanName, args);
  46. // Guarantee initialization of beans that the current bean depends on.
  47. String[] dependsOn = mbd.getDependsOn();
  48. if (dependsOn != null) {
  49. for (String dependsOnBean : dependsOn) {
  50. getBean(dependsOnBean);
  51. registerDependentBean(dependsOnBean, beanName);
  52. }
  53. }
  54. // Create bean instance.
  55. if (mbd.isSingleton()) {
  56. sharedInstance = getSingleton(beanName, new ObjectFactory() {
  57. public Object getObject() throws BeansException {
  58. try {
  59. return createBean(beanName, mbd, args);
  60. }
  61. catch (BeansException ex) {
  62. // Explicitly remove instance from singleton cache: It might have been put there
  63. // eagerly by the creation process, to allow for circular reference resolution.
  64. // Also remove any beans that received a temporary reference to the bean.
  65. destroySingleton(beanName);
  66. throw ex;
  67. }
  68. }
  69. });
  70. bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
  71. }
  72. else if (mbd.isPrototype()) {
  73. // It's a prototype -> create a new instance.
  74. Object prototypeInstance = null;
  75. try {
  76. beforePrototypeCreation(beanName);
  77. prototypeInstance = createBean(beanName, mbd, args);
  78. }
  79. finally {
  80. afterPrototypeCreation(beanName);
  81. }
  82. bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
  83. }
  84. else {
  85. String scopeName = mbd.getScope();
  86. final Scope scope = this.scopes.get(scopeName);
  87. if (scope == null) {
  88. throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
  89. }
  90. try {
  91. Object scopedInstance = scope.get(beanName, new ObjectFactory() {
  92. public Object getObject() throws BeansException {
  93. beforePrototypeCreation(beanName);
  94. try {
  95. return createBean(beanName, mbd, args);
  96. }
  97. finally {
  98. afterPrototypeCreation(beanName);
  99. }
  100. }
  101. });
  102. bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
  103. }
  104. catch (IllegalStateException ex) {
  105. throw new BeanCreationException(beanName,
  106. "Scope '" + scopeName + "' is not active for the current thread; " +
  107. "consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",
  108. ex);
  109. }
  110. }
  111. }
  112. // Check if required type matches the type of the actual bean instance.
  113. if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
  114. throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
  115. }
  116. return (T) bean;
  117. }

看这个代码英文注释就明白了

1、Eagerly check singleton cache for manually registered singletons.

2、Check if bean definition exists in this factory.Not found -> check parent.(当前BeanFactory不存在,则通过递归,向上寻找。parentBeanFactory是XmlBeanFactory的成员变量。)

3、Guarantee initialization of beans that the current bean depends on.(生成依赖bean)

4、Create bean instance.(创建bean)(创建bean的过程会查看是singleton还是prototype,如果是singleton是单例模式,只会被创建一次,prototype则每次getBean相当于new一次。代码中首先通过Object sharedInstance = getSingleton(beanName);根据bean名称获取单例对象,若为空再创建);

  1. @Override
  2. protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
  3. throws BeanCreationException {
  4. if (logger.isDebugEnabled()) {
  5. logger.debug("Creating instance of bean '" + beanName + "'");
  6. }
  7. // Make sure bean class is actually resolved at this point.
  8. resolveBeanClass(mbd, beanName);
  9. // Prepare method overrides.
  10. try {
  11. mbd.prepareMethodOverrides();
  12. }
  13. catch (BeanDefinitionValidationException ex) {
  14. throw new BeanDefinitionStoreException(mbd.getResourceDescription(),
  15. beanName, "Validation of method overrides failed", ex);
  16. }
  17. try {
  18. // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
  19. Object bean = resolveBeforeInstantiation(beanName, mbd);
  20. if (bean != null) {
  21. return bean;
  22. }
  23. }
  24. catch (Throwable ex) {
  25. throw new BeanCreationException(mbd.getResourceDescription(), beanName,
  26. "BeanPostProcessor before instantiation of bean failed", ex);
  27. }
  28. Object beanInstance = doCreateBean(beanName, mbd, args);
  29. if (logger.isDebugEnabled()) {
  30. logger.debug("Finished creating instance of bean '" + beanName + "'");
  31. }
  32. return beanInstance;
  33. }

通过注解理解其意义:

// Make sure bean class is actually resolved at this point.(确保bean类此时已被分解)
resolveBeanClass(mbd, beanName);

// Prepare method overrides.(准备实现接口的方法)

mbd.prepareMethodOverrides();

// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.(如果可能的话,返回一个代理而不是实例的对象)
Object bean = resolveBeforeInstantiation(beanName, mbd);

最后这里才是真正核心的实例化bean的方法:

Object beanInstance = doCreateBean(beanName, mbd, args);

doCreateBean中有两个重要的方法,一个是createBeanInstance,用于实例化bean。

另一个是这句populateBean(beanName, mbd, instanceWrapper);这个方法用于依赖关系的处理过程。

  1. /**
  2. * Actually create the specified bean. Pre-creation processing has already happened
  3. * at this point, e.g. checking <code>postProcessBeforeInstantiation</code> callbacks.
  4. * <p>Differentiates between default bean instantiation, use of a
  5. * factory method, and autowiring a constructor.
  6. * @param beanName the name of the bean
  7. * @param mbd the merged bean definition for the bean
  8. * @param args arguments to use if creating a prototype using explicit arguments to a
  9. * static factory method. This parameter must be <code>null</code> except in this case.
  10. * @return a new instance of the bean
  11. * @throws BeanCreationException if the bean could not be created
  12. * @see #instantiateBean
  13. * @see #instantiateUsingFactoryMethod
  14. * @see #autowireConstructor
  15. */
  16. protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
  17. // Instantiate the bean.
  18. BeanWrapper instanceWrapper = null;
  19. if (mbd.isSingleton()) {
  20. instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
  21. }
  22. if (instanceWrapper == null) {
  23. instanceWrapper = createBeanInstance(beanName, mbd, args);
  24. }
  25. final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
  26. Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
  27. // Allow post-processors to modify the merged bean definition.
  28. synchronized (mbd.postProcessingLock) {
  29. if (!mbd.postProcessed) {
  30. applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
  31. mbd.postProcessed = true;
  32. }
  33. }
  34. // Eagerly cache singletons to be able to resolve circular references
  35. // even when triggered by lifecycle interfaces like BeanFactoryAware.
  36. boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
  37. isSingletonCurrentlyInCreation(beanName));
  38. if (earlySingletonExposure) {
  39. if (logger.isDebugEnabled()) {
  40. logger.debug("Eagerly caching bean '" + beanName +
  41. "' to allow for resolving potential circular references");
  42. }
  43. addSingletonFactory(beanName, new ObjectFactory() {
  44. public Object getObject() throws BeansException {
  45. return getEarlyBeanReference(beanName, mbd, bean);
  46. }
  47. });
  48. }
  49. // Initialize the bean instance.
  50. Object exposedObject = bean;
  51. try {
  52. populateBean(beanName, mbd, instanceWrapper);
  53. if (exposedObject != null) {
  54. exposedObject = initializeBean(beanName, exposedObject, mbd);
  55. }
  56. }
  57. catch (Throwable ex) {
  58. if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
  59. throw (BeanCreationException) ex;
  60. }
  61. else {
  62. throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
  63. }
  64. }
  65. if (earlySingletonExposure) {
  66. Object earlySingletonReference = getSingleton(beanName, false);
  67. if (earlySingletonReference != null) {
  68. if (exposedObject == bean) {
  69. exposedObject = earlySingletonReference;
  70. }
  71. else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
  72. String[] dependentBeans = getDependentBeans(beanName);
  73. Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
  74. for (String dependentBean : dependentBeans) {
  75. if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
  76. actualDependentBeans.add(dependentBean);
  77. }
  78. }
  79. if (!actualDependentBeans.isEmpty()) {
  80. throw new BeanCurrentlyInCreationException(beanName,
  81. "Bean with name '" + beanName + "' has been injected into other beans [" +
  82. StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
  83. "] in its raw version as part of a circular reference, but has eventually been " +
  84. "wrapped. This means that said other beans do not use the final version of the " +
  85. "bean. This is often the result of over-eager type matching - consider using " +
  86. "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
  87. }
  88. }
  89. }
  90. }
  91. // Register bean as disposable.
  92. try {
  93. registerDisposableBeanIfNecessary(beanName, bean, mbd);
  94. }
  95. catch (BeanDefinitionValidationException ex) {
  96. throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
  97. }
  98. return exposedObject;
  99. }

这里面createBeanInstance方法用于实例化bean。下面可以看到实例化的bean的方式不止一种,有工厂方法方式,也有构造方法方式。主要根据BeanDefinition中的信息。

  1. /**
  2. * Create a new instance for the specified bean, using an appropriate instantiation strategy:
  3. * factory method, constructor autowiring, or simple instantiation.
  4. * @param beanName the name of the bean
  5. * @param mbd the bean definition for the bean
  6. * @param args arguments to use if creating a prototype using explicit arguments to a
  7. * static factory method. It is invalid to use a non-null args value in any other case.
  8. * @return BeanWrapper for the new instance
  9. * @see #instantiateUsingFactoryMethod
  10. * @see #autowireConstructor
  11. * @see #instantiateBean
  12. */
  13. protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
  14. // Make sure bean class is actually resolved at this point.
  15. Class beanClass = resolveBeanClass(mbd, beanName);
  16. if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
  17. throw new BeanCreationException(mbd.getResourceDescription(), beanName,
  18. "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
  19. }
  20. if (mbd.getFactoryMethodName() != null)  {
  21. return instantiateUsingFactoryMethod(beanName, mbd, args);
  22. }
  23. // Shortcut when re-creating the same bean...
  24. boolean resolved = false;
  25. boolean autowireNecessary = false;
  26. if (args == null) {
  27. synchronized (mbd.constructorArgumentLock) {
  28. if (mbd.resolvedConstructorOrFactoryMethod != null) {
  29. resolved = true;
  30. autowireNecessary = mbd.constructorArgumentsResolved;
  31. }
  32. }
  33. }
  34. if (resolved) {
  35. if (autowireNecessary) {
  36. return autowireConstructor(beanName, mbd, null, null);
  37. }
  38. else {
  39. return instantiateBean(beanName, mbd);
  40. }
  41. }
  42. // Need to determine the constructor...
  43. Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
  44. if (ctors != null ||
  45. mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
  46. mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
  47. return autowireConstructor(beanName, mbd, ctors, args);
  48. }
  49. // No special handling: simply use no-arg constructor.
  50. return instantiateBean(beanName, mbd);
  51. }

工厂方法模式:

  1. /**
  2. * Instantiate the bean using a named factory method. The method may be static, if the
  3. * bean definition parameter specifies a class, rather than a "factory-bean", or
  4. * an instance variable on a factory object itself configured using Dependency Injection.
  5. * <p>Implementation requires iterating over the static or instance methods with the
  6. * name specified in the RootBeanDefinition (the method may be overloaded) and trying
  7. * to match with the parameters. We don't have the types attached to constructor args,
  8. * so trial and error is the only way to go here. The explicitArgs array may contain
  9. * argument values passed in programmatically via the corresponding getBean method.
  10. * @param beanName the name of the bean
  11. * @param mbd the merged bean definition for the bean
  12. * @param explicitArgs argument values passed in programmatically via the getBean
  13. * method, or <code>null</code> if none (-> use constructor argument values from bean definition)
  14. * @return a BeanWrapper for the new instance
  15. */
  16. public BeanWrapper instantiateUsingFactoryMethod(final String beanName, final RootBeanDefinition mbd, final Object[] explicitArgs) {
  17. BeanWrapperImpl bw = new BeanWrapperImpl();
  18. this.beanFactory.initBeanWrapper(bw);
  19. Object factoryBean;
  20. Class factoryClass;
  21. boolean isStatic;
  22. String factoryBeanName = mbd.getFactoryBeanName();
  23. if (factoryBeanName != null) {
  24. if (factoryBeanName.equals(beanName)) {
  25. throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
  26. "factory-bean reference points back to the same bean definition");
  27. }
  28. factoryBean = this.beanFactory.getBean(factoryBeanName);
  29. if (factoryBean == null) {
  30. throw new BeanCreationException(mbd.getResourceDescription(), beanName,
  31. "factory-bean '" + factoryBeanName + "' returned null");
  32. }
  33. factoryClass = factoryBean.getClass();
  34. isStatic = false;
  35. }
  36. else {
  37. // It's a static factory method on the bean class.
  38. if (!mbd.hasBeanClass()) {
  39. throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
  40. "bean definition declares neither a bean class nor a factory-bean reference");
  41. }
  42. factoryBean = null;
  43. factoryClass = mbd.getBeanClass();
  44. isStatic = true;
  45. }
  46. Method factoryMethodToUse = null;
  47. ArgumentsHolder argsHolderToUse = null;
  48. Object[] argsToUse = null;
  49. if (explicitArgs != null) {
  50. argsToUse = explicitArgs;
  51. }
  52. else {
  53. Object[] argsToResolve = null;
  54. synchronized (mbd.constructorArgumentLock) {
  55. factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;
  56. if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {
  57. // Found a cached factory method...
  58. argsToUse = mbd.resolvedConstructorArguments;
  59. if (argsToUse == null) {
  60. argsToResolve = mbd.preparedConstructorArguments;
  61. }
  62. }
  63. }
  64. if (argsToResolve != null) {
  65. argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve);
  66. }
  67. }
  68. if (factoryMethodToUse == null || argsToUse == null) {
  69. // Need to determine the factory method...
  70. // Try all methods with this name to see if they match the given arguments.
  71. factoryClass = ClassUtils.getUserClass(factoryClass);
  72. Method[] rawCandidates;
  73. final Class factoryClazz = factoryClass;
  74. if (System.getSecurityManager() != null) {
  75. rawCandidates = AccessController.doPrivileged(new PrivilegedAction<Method[]>() {
  76. public Method[] run() {
  77. return (mbd.isNonPublicAccessAllowed() ?
  78. ReflectionUtils.getAllDeclaredMethods(factoryClazz) : factoryClazz.getMethods());
  79. }
  80. });
  81. }
  82. else {
  83. rawCandidates = (mbd.isNonPublicAccessAllowed() ?
  84. ReflectionUtils.getAllDeclaredMethods(factoryClazz) : factoryClazz.getMethods());
  85. }
  86. List<Method> candidateSet = new ArrayList<Method>();
  87. for (Method candidate : rawCandidates) {
  88. if (Modifier.isStatic(candidate.getModifiers()) == isStatic &&
  89. candidate.getName().equals(mbd.getFactoryMethodName()) &&
  90. mbd.isFactoryMethod(candidate)) {
  91. candidateSet.add(candidate);
  92. }
  93. }
  94. Method[] candidates = candidateSet.toArray(new Method[candidateSet.size()]);
  95. AutowireUtils.sortFactoryMethods(candidates);
  96. ConstructorArgumentValues resolvedValues = null;
  97. boolean autowiring = (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
  98. int minTypeDiffWeight = Integer.MAX_VALUE;
  99. Set<Method> ambiguousFactoryMethods = null;
  100. int minNrOfArgs;
  101. if (explicitArgs != null) {
  102. minNrOfArgs = explicitArgs.length;
  103. }
  104. else {
  105. // We don't have arguments passed in programmatically, so we need to resolve the
  106. // arguments specified in the constructor arguments held in the bean definition.
  107. ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
  108. resolvedValues = new ConstructorArgumentValues();
  109. minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
  110. }
  111. List<Exception> causes = null;
  112. for (int i = 0; i < candidates.length; i++) {
  113. Method candidate = candidates[i];
  114. Class[] paramTypes = candidate.getParameterTypes();
  115. if (paramTypes.length >= minNrOfArgs) {
  116. ArgumentsHolder argsHolder;
  117. if (resolvedValues != null) {
  118. // Resolved constructor arguments: type conversion and/or autowiring necessary.
  119. try {
  120. String[] paramNames = null;
  121. ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
  122. if (pnd != null) {
  123. paramNames = pnd.getParameterNames(candidate);
  124. }
  125. argsHolder = createArgumentArray(
  126. beanName, mbd, resolvedValues, bw, paramTypes, paramNames, candidate, autowiring);
  127. }
  128. catch (UnsatisfiedDependencyException ex) {
  129. if (this.beanFactory.logger.isTraceEnabled()) {
  130. this.beanFactory.logger.trace("Ignoring factory method [" + candidate +
  131. "] of bean '" + beanName + "': " + ex);
  132. }
  133. if (i == candidates.length - 1 && argsHolderToUse == null) {
  134. if (causes != null) {
  135. for (Exception cause : causes) {
  136. this.beanFactory.onSuppressedException(cause);
  137. }
  138. }
  139. throw ex;
  140. }
  141. else {
  142. // Swallow and try next overloaded factory method.
  143. if (causes == null) {
  144. causes = new LinkedList<Exception>();
  145. }
  146. causes.add(ex);
  147. continue;
  148. }
  149. }
  150. }
  151. else {
  152. // Explicit arguments given -> arguments length must match exactly.
  153. if (paramTypes.length != explicitArgs.length) {
  154. continue;
  155. }
  156. argsHolder = new ArgumentsHolder(explicitArgs);
  157. }
  158. int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
  159. argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
  160. // Choose this factory method if it represents the closest match.
  161. if (typeDiffWeight < minTypeDiffWeight) {
  162. factoryMethodToUse = candidate;
  163. argsHolderToUse = argsHolder;
  164. argsToUse = argsHolder.arguments;
  165. minTypeDiffWeight = typeDiffWeight;
  166. ambiguousFactoryMethods = null;
  167. }
  168. else if (factoryMethodToUse != null && typeDiffWeight == minTypeDiffWeight) {
  169. if (ambiguousFactoryMethods == null) {
  170. ambiguousFactoryMethods = new LinkedHashSet<Method>();
  171. ambiguousFactoryMethods.add(factoryMethodToUse);
  172. }
  173. ambiguousFactoryMethods.add(candidate);
  174. }
  175. }
  176. }
  177. if (factoryMethodToUse == null) {
  178. boolean hasArgs = (resolvedValues.getArgumentCount() > 0);
  179. String argDesc = "";
  180. if (hasArgs) {
  181. List<String> argTypes = new ArrayList<String>();
  182. for (ValueHolder value : resolvedValues.getIndexedArgumentValues().values()) {
  183. String argType = (value.getType() != null ?
  184. ClassUtils.getShortName(value.getType()) : value.getValue().getClass().getSimpleName());
  185. argTypes.add(argType);
  186. }
  187. argDesc = StringUtils.collectionToCommaDelimitedString(argTypes);
  188. }
  189. throw new BeanCreationException(mbd.getResourceDescription(), beanName,
  190. "No matching factory method found: " +
  191. (mbd.getFactoryBeanName() != null ?
  192. "factory bean '" + mbd.getFactoryBeanName() + "'; " : "") +
  193. "factory method '" + mbd.getFactoryMethodName() + "(" + argDesc + ")'. " +
  194. "Check that a method with the specified name " +
  195. (hasArgs ? "and arguments " : "") +
  196. "exists and that it is " +
  197. (isStatic ? "static" : "non-static") + ".");
  198. }
  199. else if (void.class.equals(factoryMethodToUse.getReturnType())) {
  200. throw new BeanCreationException(mbd.getResourceDescription(), beanName,
  201. "Invalid factory method '" + mbd.getFactoryMethodName() +
  202. "': needs to have a non-void return type!");
  203. }
  204. else if (ambiguousFactoryMethods != null && !mbd.isLenientConstructorResolution()) {
  205. throw new BeanCreationException(mbd.getResourceDescription(), beanName,
  206. "Ambiguous factory method matches found in bean '" + beanName + "' " +
  207. "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
  208. ambiguousFactoryMethods);
  209. }
  210. if (explicitArgs == null && argsHolderToUse != null) {
  211. argsHolderToUse.storeCache(mbd, factoryMethodToUse);
  212. }
  213. }
  214. try {
  215. Object beanInstance;
  216. if (System.getSecurityManager() != null) {
  217. final Object fb = factoryBean;
  218. final Method factoryMethod = factoryMethodToUse;
  219. final Object[] args = argsToUse;
  220. beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
  221. public Object run() {
  222. return beanFactory.getInstantiationStrategy().instantiate(
  223. mbd, beanName, beanFactory, fb, factoryMethod, args);
  224. }
  225. }, beanFactory.getAccessControlContext());
  226. }
  227. else {
  228. beanInstance = beanFactory.getInstantiationStrategy().instantiate(
  229. mbd, beanName, beanFactory, factoryBean, factoryMethodToUse, argsToUse);
  230. }
  231. if (beanInstance == null) {
  232. return null;
  233. }
  234. bw.setWrappedInstance(beanInstance);
  235. return bw;
  236. }
  237. catch (Throwable ex) {
  238. throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
  239. }
  240. }

构造函数方式:

  1. /**
  2. * "autowire constructor" (with constructor arguments by type) behavior.
  3. * Also applied if explicit constructor argument values are specified,
  4. * matching all remaining arguments with beans from the bean factory.
  5. * <p>This corresponds to constructor injection: In this mode, a Spring
  6. * bean factory is able to host components that expect constructor-based
  7. * dependency resolution.
  8. * @param beanName the name of the bean
  9. * @param mbd the merged bean definition for the bean
  10. * @param chosenCtors chosen candidate constructors (or <code>null</code> if none)
  11. * @param explicitArgs argument values passed in programmatically via the getBean method,
  12. * or <code>null</code> if none (-> use constructor argument values from bean definition)
  13. * @return a BeanWrapper for the new instance
  14. */
  15. public BeanWrapper autowireConstructor(
  16. final String beanName, final RootBeanDefinition mbd, Constructor[] chosenCtors, final Object[] explicitArgs) {
  17. BeanWrapperImpl bw = new BeanWrapperImpl();
  18. this.beanFactory.initBeanWrapper(bw);
  19. Constructor constructorToUse = null;
  20. ArgumentsHolder argsHolderToUse = null;
  21. Object[] argsToUse = null;
  22. if (explicitArgs != null) {
  23. argsToUse = explicitArgs;
  24. }
  25. else {
  26. Object[] argsToResolve = null;
  27. synchronized (mbd.constructorArgumentLock) {
  28. constructorToUse = (Constructor) mbd.resolvedConstructorOrFactoryMethod;
  29. if (constructorToUse != null && mbd.constructorArgumentsResolved) {
  30. // Found a cached constructor...
  31. argsToUse = mbd.resolvedConstructorArguments;
  32. if (argsToUse == null) {
  33. argsToResolve = mbd.preparedConstructorArguments;
  34. }
  35. }
  36. }
  37. if (argsToResolve != null) {
  38. argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
  39. }
  40. }
  41. if (constructorToUse == null) {
  42. // Need to resolve the constructor.
  43. boolean autowiring = (chosenCtors != null ||
  44. mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
  45. ConstructorArgumentValues resolvedValues = null;
  46. int minNrOfArgs;
  47. if (explicitArgs != null) {
  48. minNrOfArgs = explicitArgs.length;
  49. }
  50. else {
  51. ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
  52. resolvedValues = new ConstructorArgumentValues();
  53. minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
  54. }
  55. // Take specified constructors, if any.
  56. Constructor[] candidates = chosenCtors;
  57. if (candidates == null) {
  58. Class beanClass = mbd.getBeanClass();
  59. try {
  60. candidates = (mbd.isNonPublicAccessAllowed() ?
  61. beanClass.getDeclaredConstructors() : beanClass.getConstructors());
  62. }
  63. catch (Throwable ex) {
  64. throw new BeanCreationException(mbd.getResourceDescription(), beanName,
  65. "Resolution of declared constructors on bean Class [" + beanClass.getName() +
  66. "] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
  67. }
  68. }
  69. AutowireUtils.sortConstructors(candidates);
  70. int minTypeDiffWeight = Integer.MAX_VALUE;
  71. Set<Constructor> ambiguousConstructors = null;
  72. List<Exception> causes = null;
  73. for (int i = 0; i < candidates.length; i++) {
  74. Constructor<?> candidate = candidates[i];
  75. Class[] paramTypes = candidate.getParameterTypes();
  76. if (constructorToUse != null && argsToUse.length > paramTypes.length) {
  77. // Already found greedy constructor that can be satisfied ->
  78. // do not look any further, there are only less greedy constructors left.
  79. break;
  80. }
  81. if (paramTypes.length < minNrOfArgs) {
  82. continue;
  83. }
  84. ArgumentsHolder argsHolder;
  85. if (resolvedValues != null) {
  86. try {
  87. String[] paramNames = null;
  88. if (constructorPropertiesAnnotationAvailable) {
  89. paramNames = ConstructorPropertiesChecker.evaluateAnnotation(candidate, paramTypes.length);
  90. }
  91. if (paramNames == null) {
  92. ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
  93. if (pnd != null) {
  94. paramNames = pnd.getParameterNames(candidate);
  95. }
  96. }
  97. argsHolder = createArgumentArray(
  98. beanName, mbd, resolvedValues, bw, paramTypes, paramNames, candidate, autowiring);
  99. }
  100. catch (UnsatisfiedDependencyException ex) {
  101. if (this.beanFactory.logger.isTraceEnabled()) {
  102. this.beanFactory.logger.trace(
  103. "Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
  104. }
  105. if (i == candidates.length - 1 && constructorToUse == null) {
  106. if (causes != null) {
  107. for (Exception cause : causes) {
  108. this.beanFactory.onSuppressedException(cause);
  109. }
  110. }
  111. throw ex;
  112. }
  113. else {
  114. // Swallow and try next constructor.
  115. if (causes == null) {
  116. causes = new LinkedList<Exception>();
  117. }
  118. causes.add(ex);
  119. continue;
  120. }
  121. }
  122. }
  123. else {
  124. // Explicit arguments given -> arguments length must match exactly.
  125. if (paramTypes.length != explicitArgs.length) {
  126. continue;
  127. }
  128. argsHolder = new ArgumentsHolder(explicitArgs);
  129. }
  130. int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
  131. argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
  132. // Choose this constructor if it represents the closest match.
  133. if (typeDiffWeight < minTypeDiffWeight) {
  134. constructorToUse = candidate;
  135. argsHolderToUse = argsHolder;
  136. argsToUse = argsHolder.arguments;
  137. minTypeDiffWeight = typeDiffWeight;
  138. ambiguousConstructors = null;
  139. }
  140. else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
  141. if (ambiguousConstructors == null) {
  142. ambiguousConstructors = new LinkedHashSet<Constructor>();
  143. ambiguousConstructors.add(constructorToUse);
  144. }
  145. ambiguousConstructors.add(candidate);
  146. }
  147. }
  148. if (constructorToUse == null) {
  149. throw new BeanCreationException(mbd.getResourceDescription(), beanName,
  150. "Could not resolve matching constructor " +
  151. "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
  152. }
  153. else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
  154. throw new BeanCreationException(mbd.getResourceDescription(), beanName,
  155. "Ambiguous constructor matches found in bean '" + beanName + "' " +
  156. "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
  157. ambiguousConstructors);
  158. }
  159. if (explicitArgs == null) {
  160. argsHolderToUse.storeCache(mbd, constructorToUse);
  161. }
  162. }
  163. try {
  164. Object beanInstance;
  165. if (System.getSecurityManager() != null) {
  166. final Constructor ctorToUse = constructorToUse;
  167. final Object[] argumentsToUse = argsToUse;
  168. beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
  169. public Object run() {
  170. return beanFactory.getInstantiationStrategy().instantiate(
  171. mbd, beanName, beanFactory, ctorToUse, argumentsToUse);
  172. }
  173. }, beanFactory.getAccessControlContext());
  174. }
  175. else {
  176. beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(
  177. mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
  178. }
  179. bw.setWrappedInstance(beanInstance);
  180. return bw;
  181. }
  182. catch (Throwable ex) {
  183. throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
  184. }
  185. }

采用默认构造函数方式(这也是spring默认的形式)主要看看这个的代码:

  1. /**
  2. * Instantiate the given bean using its default constructor.
  3. * @param beanName the name of the bean
  4. * @param mbd the bean definition for the bean
  5. * @return BeanWrapper for the new instance
  6. */
  7. protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
  8. try {
  9. Object beanInstance;
  10. final BeanFactory parent = this;
  11. if (System.getSecurityManager() != null) {
  12. beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
  13. public Object run() {
  14. return getInstantiationStrategy().instantiate(mbd, beanName, parent);
  15. }
  16. }, getAccessControlContext());
  17. }
  18. else {
  19. beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
  20. }
  21. BeanWrapper bw = new BeanWrapperImpl(beanInstance);
  22. initBeanWrapper(bw);
  23. return bw;
  24. }
  25. catch (Throwable ex) {
  26. throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
  27. }
  28. }

继续跟踪比较核心的getInstantiationStrategy().instantiate(mbd, beanName, parent):

  1. /**
  2. * Simple object instantiation strategy for use in a BeanFactory.
  3. *
  4. * <p>Does not support Method Injection, although it provides hooks for subclasses
  5. * to override to add Method Injection support, for example by overriding methods.
  6. *
  7. * @author Rod Johnson
  8. * @author Juergen Hoeller
  9. * @since 1.1
  10. */
  11. public class SimpleInstantiationStrategy implements InstantiationStrategy {
  12. public Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) {
  13. // Don't override the class with CGLIB if no overrides.
  14. if (beanDefinition.getMethodOverrides().isEmpty()) {
  15. Constructor<?> constructorToUse;
  16. synchronized (beanDefinition.constructorArgumentLock) {
  17. constructorToUse = (Constructor<?>) beanDefinition.resolvedConstructorOrFactoryMethod;
  18. if (constructorToUse == null) {
  19. final Class clazz = beanDefinition.getBeanClass();
  20. if (clazz.isInterface()) {
  21. throw new BeanInstantiationException(clazz, "Specified class is an interface");
  22. }
  23. try {
  24. if (System.getSecurityManager() != null) {
  25. constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor>() {
  26. public Constructor run() throws Exception {
  27. return clazz.getDeclaredConstructor((Class[]) null);
  28. }
  29. });
  30. }
  31. else {
  32. constructorToUse =  clazz.getDeclaredConstructor((Class[]) null);
  33. }
  34. beanDefinition.resolvedConstructorOrFactoryMethod = constructorToUse;
  35. }
  36. catch (Exception ex) {
  37. throw new BeanInstantiationException(clazz, "No default constructor found", ex);
  38. }
  39. }
  40. }
  41. return BeanUtils.instantiateClass(constructorToUse);
  42. }
  43. else {
  44. // Must generate CGLIB subclass.
  45. return instantiateWithMethodInjection(beanDefinition, beanName, owner);
  46. }
  47. }

最后一句return instantiateWithMethodInjection(beanDefinition, beanName, owner);便是采用CGLIB的方式。上面的代码BeanUtils.instantiateClass(constructorToUse);是使用构造器或生成对象的工厂方法来实例化。

cglib代码包结构

(是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java类与实现Java接口。Hibernate用它来实现PO(Persistent Object 持久化对象)字节码的动态生成。)

  • core (核心代码)
    • EmitUtils
    • ReflectUtils
    • KeyFactory
    • ClassEmitter/CodeEmitter
    • NamingPolicy/DefaultNamingPolicy
    • GeneratorStrategy/DefaultGeneratorStrategy
    • DebuggingClassWriter
    • ClassGenerator/AbstractClassGenerator
  • beans (bean操作类)
    • BeanCopier
    • BulkBean
    • BeanMap
    • ImmutableBean
    • BeanGenerator
  • reflect
    • FastClass
  • proxy
    • MethodInterceptor , Dispatcher, LazyLoader , ProxyRefDispatcher , NoOp , FixedValue , InvocationHandler(提供和jdk proxy的功能)
    • Enhancer
    • CallbackGenerator
    • Callback
    • CallbackFilter
  • util
    • StringSwitcher
    • ParallelSorter
  • transform

继续跟踪具体的cglib实例化bean的代码:

  1. /**
  2. * Create a new instance of a dynamically generated subclasses implementing the
  3. * required lookups.
  4. * @param ctor constructor to use. If this is <code>null</code>, use the
  5. * no-arg constructor (no parameterization, or Setter Injection)
  6. * @param args arguments to use for the constructor.
  7. * Ignored if the ctor parameter is <code>null</code>.
  8. * @return new instance of the dynamically generated class
  9. */
  10. public Object instantiate(Constructor ctor, Object[] args) {
  11. Enhancer enhancer = new Enhancer();
  12. enhancer.setSuperclass(this.beanDefinition.getBeanClass());
  13. enhancer.setCallbackFilter(new CallbackFilterImpl());
  14. enhancer.setCallbacks(new Callback[] {
  15. NoOp.INSTANCE,
  16. new LookupOverrideMethodInterceptor(),
  17. new ReplaceOverrideMethodInterceptor()
  18. });
  19. return (ctor == null) ?
  20. enhancer.create() :
  21. enhancer.create(ctor.getParameterTypes(), args);
  22. }

跟踪一下BeanUtils.instantiateClass(constructorToUse);

  1. /**
  2. * Convenience method to instantiate a class using the given constructor.
  3. * As this method doesn't try to load classes by name, it should avoid
  4. * class-loading issues.
  5. * <p>Note that this method tries to set the constructor accessible
  6. * if given a non-accessible (that is, non-public) constructor.
  7. * @param ctor the constructor to instantiate
  8. * @param args the constructor arguments to apply
  9. * @return the new instance
  10. * @throws BeanInstantiationException if the bean cannot be instantiated
  11. */
  12. public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
  13. Assert.notNull(ctor, "Constructor must not be null");
  14. try {
  15. ReflectionUtils.makeAccessible(ctor);
  16. return ctor.newInstance(args);
  17. }
  18. catch (InstantiationException ex) {
  19. throw new BeanInstantiationException(ctor.getDeclaringClass(),
  20. "Is it an abstract class?", ex);
  21. }
  22. catch (IllegalAccessException ex) {
  23. throw new BeanInstantiationException(ctor.getDeclaringClass(),
  24. "Is the constructor accessible?", ex);
  25. }
  26. catch (IllegalArgumentException ex) {
  27. throw new BeanInstantiationException(ctor.getDeclaringClass(),
  28. "Illegal arguments for constructor", ex);
  29. }
  30. catch (InvocationTargetException ex) {
  31. throw new BeanInstantiationException(ctor.getDeclaringClass(),
  32. "Constructor threw exception", ex.getTargetException());
  33. }
  34. }

用到了Reflection类,是使用了反射。

  1. /**
  2. * Uses the constructor represented by this {@code Constructor} object to
  3. * create and initialize a new instance of the constructor's
  4. * declaring class, with the specified initialization parameters.
  5. * Individual parameters are automatically unwrapped to match
  6. * primitive formal parameters, and both primitive and reference
  7. * parameters are subject to method invocation conversions as necessary.
  8. *
  9. * <p>If the number of formal parameters required by the underlying constructor
  10. * is 0, the supplied {@code initargs} array may be of length 0 or null.
  11. *
  12. * <p>If the constructor's declaring class is an inner class in a
  13. * non-static context, the first argument to the constructor needs
  14. * to be the enclosing instance; see section 15.9.3 of
  15. * <cite>The Java™ Language Specification</cite>.
  16. *
  17. * <p>If the required access and argument checks succeed and the
  18. * instantiation will proceed, the constructor's declaring class
  19. * is initialized if it has not already been initialized.
  20. *
  21. * <p>If the constructor completes normally, returns the newly
  22. * created and initialized instance.
  23. *
  24. * @param initargs array of objects to be passed as arguments to
  25. * the constructor call; values of primitive types are wrapped in
  26. * a wrapper object of the appropriate type (e.g. a {@code float}
  27. * in a {@link java.lang.Float Float})
  28. *
  29. * @return a new object created by calling the constructor
  30. * this object represents
  31. *
  32. * @exception IllegalAccessException    if this {@code Constructor} object
  33. *              is enforcing Java language access control and the underlying
  34. *              constructor is inaccessible.
  35. * @exception IllegalArgumentException  if the number of actual
  36. *              and formal parameters differ; if an unwrapping
  37. *              conversion for primitive arguments fails; or if,
  38. *              after possible unwrapping, a parameter value
  39. *              cannot be converted to the corresponding formal
  40. *              parameter type by a method invocation conversion; if
  41. *              this constructor pertains to an enum type.
  42. * @exception InstantiationException    if the class that declares the
  43. *              underlying constructor represents an abstract class.
  44. * @exception InvocationTargetException if the underlying constructor
  45. *              throws an exception.
  46. * @exception ExceptionInInitializerError if the initialization provoked
  47. *              by this method fails.
  48. */
  49. @CallerSensitive
  50. public T newInstance(Object ... initargs)
  51. throws InstantiationException, IllegalAccessException,
  52. IllegalArgumentException, InvocationTargetException
  53. {
  54. if (!override) {
  55. if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
  56. Class<?> caller = Reflection.getCallerClass();
  57. checkAccess(caller, clazz, null, modifiers);
  58. }
  59. }
  60. if ((clazz.getModifiers() & Modifier.ENUM) != 0)
  61. throw new IllegalArgumentException("Cannot reflectively create enum objects");
  62. ConstructorAccessor ca = constructorAccessor;   // read volatile
  63. if (ca == null) {
  64. ca = acquireConstructorAccessor();
  65. }
  66. return (T) ca.newInstance(initargs);
  67. }

之后终于看到了populateBean这个方法,之前也说过,这是用来处理依赖关系的。在AbstractAutowireCapableBeanFactory类中:

  1. /**
  2. * Populate the bean instance in the given BeanWrapper with the property values
  3. * from the bean definition.
  4. * @param beanName the name of the bean
  5. * @param mbd the bean definition for the bean
  6. * @param bw BeanWrapper with bean instance
  7. */
  8. protected void populateBean(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw) {
  9. PropertyValues pvs = mbd.getPropertyValues();
  10. if (bw == null) {
  11. if (!pvs.isEmpty()) {
  12. throw new BeanCreationException(
  13. mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
  14. }
  15. else {
  16. // Skip property population phase for null instance.
  17. return;
  18. }
  19. }
  20. // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
  21. // state of the bean before properties are set. This can be used, for example,
  22. // to support styles of field injection.
  23. boolean continueWithPropertyPopulation = true;
  24. if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
  25. for (BeanPostProcessor bp : getBeanPostProcessors()) {
  26. if (bp instanceof InstantiationAwareBeanPostProcessor) {
  27. InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
  28. if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
  29. continueWithPropertyPopulation = false;
  30. break;
  31. }
  32. }
  33. }
  34. }
  35. if (!continueWithPropertyPopulation) {
  36. return;
  37. }
  38. if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
  39. mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
  40. MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
  41. // Add property values based on autowire by name if applicable.
  42. if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
  43. autowireByName(beanName, mbd, bw, newPvs);
  44. }
  45. // Add property values based on autowire by type if applicable.
  46. if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
  47. autowireByType(beanName, mbd, bw, newPvs);
  48. }
  49. pvs = newPvs;
  50. }
  51. boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
  52. boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
  53. if (hasInstAwareBpps || needsDepCheck) {
  54. PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw);
  55. if (hasInstAwareBpps) {
  56. for (BeanPostProcessor bp : getBeanPostProcessors()) {
  57. if (bp instanceof InstantiationAwareBeanPostProcessor) {
  58. InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
  59. pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
  60. if (pvs == null) {
  61. return;
  62. }
  63. }
  64. }
  65. }
  66. if (needsDepCheck) {
  67. checkDependencies(beanName, mbd, filteredPds, pvs);
  68. }
  69. }
  70. applyPropertyValues(beanName, mbd, bw, pvs);
  71. }

设断点单步跟踪,可知PropertyValues pvs = mbd.getPropertyValues();这句是获取该bean的所有属性。

真正核心的是最后这句,其中PropertyValues pvs作为其参数:

  1. /**
  2. * Apply the given property values, resolving any runtime references
  3. * to other beans in this bean factory. Must use deep copy, so we
  4. * don't permanently modify this property.
  5. * @param beanName the bean name passed for better exception information
  6. * @param mbd the merged bean definition
  7. * @param bw the BeanWrapper wrapping the target object
  8. * @param pvs the new property values
  9. */
  10. protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
  11. if (pvs == null || pvs.isEmpty()) {
  12. return;
  13. }
  14. MutablePropertyValues mpvs = null;
  15. List<PropertyValue> original;
  16. if (System.getSecurityManager()!= null) {
  17. if (bw instanceof BeanWrapperImpl) {
  18. ((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
  19. }
  20. }
  21. if (pvs instanceof MutablePropertyValues) {
  22. mpvs = (MutablePropertyValues) pvs;
  23. if (mpvs.isConverted()) {
  24. // Shortcut: use the pre-converted values as-is.
  25. try {
  26. bw.setPropertyValues(mpvs);
  27. return;
  28. }
  29. catch (BeansException ex) {
  30. throw new BeanCreationException(
  31. mbd.getResourceDescription(), beanName, "Error setting property values", ex);
  32. }
  33. }
  34. original = mpvs.getPropertyValueList();
  35. }
  36. else {
  37. original = Arrays.asList(pvs.getPropertyValues());
  38. }
  39. TypeConverter converter = getCustomTypeConverter();
  40. if (converter == null) {
  41. converter = bw;
  42. }
  43. BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);
  44. // Create a deep copy, resolving any references for values.
  45. List<PropertyValue> deepCopy = new ArrayList<PropertyValue>(original.size());
  46. boolean resolveNecessary = false;
  47. for (PropertyValue pv : original) {
  48. if (pv.isConverted()) {
  49. deepCopy.add(pv);
  50. }
  51. else {
  52. String propertyName = pv.getName();
  53. Object originalValue = pv.getValue();
  54. Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
  55. Object convertedValue = resolvedValue;
  56. boolean convertible = bw.isWritableProperty(propertyName) &&
  57. !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
  58. if (convertible) {
  59. convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
  60. }
  61. // Possibly store converted value in merged bean definition,
  62. // in order to avoid re-conversion for every created bean instance.
  63. if (resolvedValue == originalValue) {
  64. if (convertible) {
  65. pv.setConvertedValue(convertedValue);
  66. }
  67. deepCopy.add(pv);
  68. }
  69. else if (convertible && originalValue instanceof TypedStringValue &&
  70. !((TypedStringValue) originalValue).isDynamic() &&
  71. !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
  72. pv.setConvertedValue(convertedValue);
  73. deepCopy.add(pv);
  74. }
  75. else {
  76. resolveNecessary = true;
  77. deepCopy.add(new PropertyValue(pv, convertedValue));
  78. }
  79. }
  80. }
  81. if (mpvs != null && !resolveNecessary) {
  82. mpvs.setConverted();
  83. }
  84. // Set our (possibly massaged) deep copy.
  85. try {
  86. bw.setPropertyValues(new MutablePropertyValues(deepCopy));
  87. }
  88. catch (BeansException ex) {
  89. throw new BeanCreationException(
  90. mbd.getResourceDescription(), beanName, "Error setting property values", ex);
  91. }
  92. }
  93. /**
  94. * Convert the given value for the specified target property.
  95. */
  96. private Object convertForProperty(Object value, String propertyName, BeanWrapper bw, TypeConverter converter) {
  97. if (converter instanceof BeanWrapperImpl) {
  98. return ((BeanWrapperImpl) converter).convertForProperty(value, propertyName);
  99. }
  100. else {
  101. PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
  102. MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
  103. return converter.convertIfNecessary(value, pd.getPropertyType(), methodParam);
  104. }
  105. }

这个方法很长,其内在逻辑却也不难。主要是对传进来的PropertyValues pvs参数的每一项做一个解析过程,而BeanWrapper bw参数包装着前面实例化的bean实例对象。

而BeanDefinition mbd这个参数,也就是BeanDefinition,在这里只用于抛出异常信息,没什么大用。

看代码for (PropertyValue pv : original) {}循环遍历PropertyValues,循环过程解析每一个字段:Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue),最后bw.setPropertyValues(new MutablePropertyValues(deepCopy));这句将之前得到的结果set进我们要处理的实例化对象;

  1. /**
  2. * Given a PropertyValue, return a value, resolving any references to other
  3. * beans in the factory if necessary. The value could be:
  4. * <li>A BeanDefinition, which leads to the creation of a corresponding
  5. * new bean instance. Singleton flags and names of such "inner beans"
  6. * are always ignored: Inner beans are anonymous prototypes.
  7. * <li>A RuntimeBeanReference, which must be resolved.
  8. * <li>A ManagedList. This is a special collection that may contain
  9. * RuntimeBeanReferences or Collections that will need to be resolved.
  10. * <li>A ManagedSet. May also contain RuntimeBeanReferences or
  11. * Collections that will need to be resolved.
  12. * <li>A ManagedMap. In this case the value may be a RuntimeBeanReference
  13. * or Collection that will need to be resolved.
  14. * <li>An ordinary object or <code>null</code>, in which case it's left alone.
  15. * @param argName the name of the argument that the value is defined for
  16. * @param value the value object to resolve
  17. * @return the resolved object
  18. */
  19. public Object resolveValueIfNecessary(Object argName, Object value) {
  20. // We must check each value to see whether it requires a runtime reference
  21. // to another bean to be resolved.
  22. if (value instanceof RuntimeBeanReference) {
  23. RuntimeBeanReference ref = (RuntimeBeanReference) value;
  24. return resolveReference(argName, ref);
  25. }
  26. else if (value instanceof RuntimeBeanNameReference) {
  27. String refName = ((RuntimeBeanNameReference) value).getBeanName();
  28. refName = String.valueOf(evaluate(refName));
  29. if (!this.beanFactory.containsBean(refName)) {
  30. throw new BeanDefinitionStoreException(
  31. "Invalid bean name '" + refName + "' in bean reference for " + argName);
  32. }
  33. return refName;
  34. }
  35. else if (value instanceof BeanDefinitionHolder) {
  36. // Resolve BeanDefinitionHolder: contains BeanDefinition with name and aliases.
  37. BeanDefinitionHolder bdHolder = (BeanDefinitionHolder) value;
  38. return resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition());
  39. }
  40. else if (value instanceof BeanDefinition) {
  41. // Resolve plain BeanDefinition, without contained name: use dummy name.
  42. BeanDefinition bd = (BeanDefinition) value;
  43. return resolveInnerBean(argName, "(inner bean)", bd);
  44. }
  45. else if (value instanceof ManagedArray) {
  46. // May need to resolve contained runtime references.
  47. ManagedArray array = (ManagedArray) value;
  48. Class elementType = array.resolvedElementType;
  49. if (elementType == null) {
  50. String elementTypeName = array.getElementTypeName();
  51. if (StringUtils.hasText(elementTypeName)) {
  52. try {
  53. elementType = ClassUtils.forName(elementTypeName, this.beanFactory.getBeanClassLoader());
  54. array.resolvedElementType = elementType;
  55. }
  56. catch (Throwable ex) {
  57. // Improve the message by showing the context.
  58. throw new BeanCreationException(
  59. this.beanDefinition.getResourceDescription(), this.beanName,
  60. "Error resolving array type for " + argName, ex);
  61. }
  62. }
  63. else {
  64. elementType = Object.class;
  65. }
  66. }
  67. return resolveManagedArray(argName, (List<?>) value, elementType);
  68. }
  69. else if (value instanceof ManagedList) {
  70. // May need to resolve contained runtime references.
  71. return resolveManagedList(argName, (List<?>) value);
  72. }
  73. else if (value instanceof ManagedSet) {
  74. // May need to resolve contained runtime references.
  75. return resolveManagedSet(argName, (Set<?>) value);
  76. }
  77. else if (value instanceof ManagedMap) {
  78. // May need to resolve contained runtime references.
  79. return resolveManagedMap(argName, (Map<?, ?>) value);
  80. }
  81. else if (value instanceof ManagedProperties) {
  82. Properties original = (Properties) value;
  83. Properties copy = new Properties();
  84. for (Map.Entry propEntry : original.entrySet()) {
  85. Object propKey = propEntry.getKey();
  86. Object propValue = propEntry.getValue();
  87. if (propKey instanceof TypedStringValue) {
  88. propKey = evaluate((TypedStringValue) propKey);
  89. }
  90. if (propValue instanceof TypedStringValue) {
  91. propValue = evaluate((TypedStringValue) propValue);
  92. }
  93. copy.put(propKey, propValue);
  94. }
  95. return copy;
  96. }
  97. else if (value instanceof TypedStringValue) {
  98. // Convert value to target type here.
  99. TypedStringValue typedStringValue = (TypedStringValue) value;
  100. Object valueObject = evaluate(typedStringValue);
  101. try {
  102. Class<?> resolvedTargetType = resolveTargetType(typedStringValue);
  103. if (resolvedTargetType != null) {
  104. return this.typeConverter.convertIfNecessary(valueObject, resolvedTargetType);
  105. }
  106. else {
  107. return valueObject;
  108. }
  109. }
  110. catch (Throwable ex) {
  111. // Improve the message by showing the context.
  112. throw new BeanCreationException(
  113. this.beanDefinition.getResourceDescription(), this.beanName,
  114. "Error converting typed String value for " + argName, ex);
  115. }
  116. }
  117. else {
  118. return evaluate(value);
  119. }
  120. }

简单总结:

一、容器初始化:

1,Resource来进行资源定位

2,spring创建工厂时(以XmlBeanFactory为例),解析xml文件,转化为document

3,注册BeanDefinition,在BeanFactory的map数据结构里。BeanDefinition就是spring内部用来描绘bean的数据结构

4,getBean时,依据BeanDefinition,实例化对象

5, populateBean 处理 前面实例化的对象的依赖关系

spring源码分析(一)IoC、DI的更多相关文章

  1. 【spring源码分析】IOC容器初始化(总结)

    前言:在经过前面十二篇文章的分析,对bean的加载流程大致梳理清楚了.因为内容过多,因此需要进行一个小总结. 经过前面十二篇文章的漫长分析,终于将xml配置文件中的bean,转换成我们实际所需要的真正 ...

  2. 【spring源码分析】IOC容器初始化(二)

    前言:在[spring源码分析]IOC容器初始化(一)文末中已经提出loadBeanDefinitions(DefaultListableBeanFactory)的重要性,本文将以此为切入点继续分析. ...

  3. 【spring源码分析】IOC容器初始化(三)

    前言:在[spring源码分析]IOC容器初始化(二)中已经得到了XML配置文件的Document实例,下面分析bean的注册过程. XmlBeanDefinitionReader#registerB ...

  4. 【spring源码分析】IOC容器初始化(四)

    前言:在[spring源码分析]IOC容器初始化(三)中已经分析了BeanDefinition注册之前的一些准备工作,下面将进入BeanDefinition注册的核心流程. //DefaultBean ...

  5. 【spring源码分析】IOC容器初始化(七)

    前言:在[spring源码分析]IOC容器初始化(六)中分析了从单例缓存中加载bean对象,由于篇幅原因其核心函数 FactoryBeanRegistrySupport#getObjectFromFa ...

  6. 【spring源码分析】IOC容器初始化(十)

    前言:前文[spring源码分析]IOC容器初始化(九)中分析了AbstractAutowireCapableBeanFactory#createBeanInstance方法中通过工厂方法创建bean ...

  7. 【spring源码分析】IOC容器初始化——查漏补缺(一)

    前言:在[spring源码分析]IOC容器初始化(十一)中提到了初始化bean的三个步骤: 激活Aware方法. 后置处理器应用(before/after). 激活自定义的init方法. 这里我们就来 ...

  8. Spring源码分析专题 —— IOC容器启动过程(上篇)

    声明 1.建议先阅读<Spring源码分析专题 -- 阅读指引> 2.强烈建议阅读过程中要参照调用过程图,每篇都有其对应的调用过程图 3.写文不易,转载请标明出处 前言 关于 IOC 容器 ...

  9. Spring源码分析之IOC的三种常见用法及源码实现(二)

    Spring源码分析之IOC的三种常见用法及源码实现(二) 回顾上文 我们研究的是 AnnotationConfigApplicationContext annotationConfigApplica ...

  10. 【spring源码分析】IOC容器初始化——查漏补缺(五)

    前言:我们知道在Spring中经常使用配置文件的形式对进行属性的赋值,那配置文件的值是怎么赋值到属性上的呢,本文将对其进行分析. 首先了解一个类:PropertySourcesPlaceholderC ...

随机推荐

  1. [C#.NET]

    Control.Refresh - does an Control.Invalidate followed by Control.Update. Refresh: 强制控件使其工作区无效并立即重绘自己 ...

  2. java安装教程

    1.安装中,jdk和jre的安装在不同的目录中 2.环境变量的配置 选择系统变量中 新建以下3个环境变量: JAVA_HOME  jdk安装路径 CLASSPATH  .;%JAVA_HOME%\li ...

  3. Process 执行shell 脚本

    概述: Process类是一个抽象类(所有的方法均是抽象的),封装了一个进程(即一个执行程序). Process 类提供了执行从进程输入.执行输出到进程.等待进程完成.检查进程的退出状态以及销毁(杀掉 ...

  4. Qt 5.7设置调试器

    mingw版本下自带的,这个我就不在赘述. 现在来说一下msvc版本下调试器,cdb,这个需要到ms去下载. thunder://QUFodHRwOi8vZG93bmxvYWQubWljcm9zb2Z ...

  5. yii 图片展示

    <?= DetailView::widget([ 'model' => $model, 'attributes' => [ 'id', 'name', 'time', 'pic', ...

  6. hdu 1342(DFS)

    Lotto Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submi ...

  7. Struts2之文件上传下载

    本篇文章主要介绍如何利用struts2进行文件的上传及下载,同时给出我在编写同时所遇到的一些问题的解决方案. 文件上传 前端页面 <!-- 引入struts标签 --> <%@tag ...

  8. Java程序,求学员的平均成绩

    第一步,系统提示输入学员的人数. 第二步,逐一获取学员的分数,并累计. 第三步,求平均成绩,并输出. import java.util.Scanner; public class chengji { ...

  9. C# IGUID的生成

    GUID(全局统一标识符)是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的.通常平台会提供生成GUID的API.生成算法很有意思,用到了以太网卡地址.纳秒级时间.芯片ID码和许多可 ...

  10. WIN8 平台应用隐私声明

    隐私权声明 本应用连接网络仅为控制硬件设备,不会收集你的个人信息,也不共享你个个人信息. 应用名称 雅典娜监控平台移动客户端 关于本应用 本应仅为控制设备应用,不关注任何配置相关信息,所有数据均来自服 ...