本文要解析的是Spring factory-method是如何来实现的,话不多说,示例先上来。
Stu.java
public class Stu { public String stuId; public Stu(String stuId) { this.stuId = stuId; } }
StuFactory.java
public class StuFactory { //动态创建类 public Stu getDynamicStu(String stuId) { return new Stu(stuId); } }
spring50.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!--生成对象的工厂--> <bean id="stuFactory" class="com.spring_1_100.test_41_50.test50.StuFactory"/> <!--动态获取对象--> <bean id="dynamicStu" factory-bean="stuFactory" factory-method="getDynamicStu"> <!--传入getDynamicStu方法的参数--> <constructor-arg value="11"/> </bean> </beans>
Test50.java
public class Test50 { public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:spring_1_100/config_41_50/spring50.xml"); //获取动态Bean Stu stu =(Stu) ac.getBean("dynamicStu"); System.out.println(JSON.toJSONString(stu)); } }
【输出结果】
{“stuId”:“11”}
首先,我们关于dynamicStu bean的解析。
BeanDefinitionParserDelegate.java
/** * 1.首先委托BeanDefinitionDelegate类的parseBeanDefinitionElement方法进行元素解析,返回BeanDefinitionHolder类型的bdHolder * ,经过这个方法后bdHolder实例己经包含我们配置文件中配置的各个属性了,例如class,name,id,alias之类的属性 * 2.当返回的bdHolder不为空的情况下若存在默认标签的子节点下再有自定义属性,还需要再次对自定义的属性进行标签解析 * 3.解析完成后,需要对解析后的bdHolder进行注册,更新,注册操作委托给了BeanDefinitionReaderUtils的registerBeanDefinition方法 * 4.最后发出响应事件,通知相关的监听器,这个bean己经加载好了 */ protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); // BeanDefinitionHolder是对BeanDefinition的封装,即Bean定义封装类 // 对文档中的元素解析由BeanDefinitionParserDelegate实现 // BeanDefinitionHolder bdHolder = deletate.parseBeanDefinitionElement(element) // BeanDefinitionHolder是对 if (bdHolder != null) { /*** * 如果需要的话就对 beanDefinition 进行装饰,那么这句代码的作用就是什么功能呢? * 这句代码的使用场景如下: * <bean id="test" class="test.MyClass"> * <mybean:user username="aaaa"/> * </bean> * 当 Spring 中的 bean 使用了默认的标签配置,但是其中的子元素却使用了自定义的配置,这句代码就起作用了,可能会有人会疑问, * 之前讲过,对 bean 的解析分成两种类型,一种是默认的类型解析,另一种是自定义类型解析,这不正是自定义类型解析吗?为什么会在 * 默认的类型解析中单独的添加一个方法的处理呢,确实,这个问题很让人迷惑,但是,不知道聪明的读者有没有发现,这个自定义类型并不是 * 以 Bean 的形式出现的呢?我们之前讲过两种类型的不同处理只是针对 bean 的,这里我们看到,这个自定义类型其实是属性,好了,我们 * 我们继续分析这个代码 */ bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); try { // 向Spring Ioc容器注册解析得到的bean定义,这是Bean定义向Ioc容器注册的入口 BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); } catch (BeanDefinitionStoreException ex) { getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, ex); } // 在完成向Spring IoC容器注册解析得到的Bean定义之后,发送注册事件 getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder)); } }
BeanDefinitionParserDelegate.java
/** * 解析bean元素的入口 */ public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) { return parseBeanDefinitionElement(ele, null); }
BeanDefinitionParserDelegate.java
/** * 解析Bean配置信息中的元素,这个方法中主要处理的元素的id,name,别名属性 */ public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) { // 获取元素中的id属性值 String id = ele.getAttribute(ID_ATTRIBUTE); // 获取元素的name属性值 String nameAttr = ele.getAttribute(NAME_ATTRIBUTE); // 获取bean元素的alias属性值 List<String> aliases = new ArrayList(); // 将元素的中的所有alias属性值放入到别名中 if (StringUtils.hasLength(nameAttr)) { String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS); aliases.addAll(Arrays.asList(nameArr)); } String beanName = id; // 如果元素中没有配置id属性,将别名中的第一个值赋值给beanName if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) { beanName = aliases.remove(0); if (logger.isDebugEnabled()) { logger.debug("No XML 'id' specified - using '" + beanName + "' as bean name and " + aliases + " as aliases"); } } // 检查元素所配置的id或者name唯一性 if (containingBean == null) { //检查元素的所配置的id,name或者别名是否重复 checkNameUniqueness(beanName, aliases, ele); } // 详细对元素中的配置的bean定义进行解析 AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean); if (beanDefinition != null) { if (!StringUtils.hasText(beanName)) { try { if (containingBean != null) { // 如果元素中没有配置id,别名或者name,且没有包含子元素 // 元素,则解析的Bean生成一个唯一的beanName并注册 beanName = BeanDefinitionReaderUtils.generateBeanName( beanDefinition, this.readerContext.getRegistry(), true); } else { // 如果元素没有配置id,别名或者name,且包含子元素 // <bean>元素,则将解析的Bean生成一个唯一的BeanName并注册 beanName = this.readerContext.generateBeanName(beanDefinition); String beanClassName = beanDefinition.getBeanClassName(); // 为解析的Bean使用别名注册时,为了向后兼容 // Spring 1.2 /2.0 给别名添加后缀 if (beanClassName != null && beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() && !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) { aliases.add(beanClassName); } } if (logger.isDebugEnabled()) { logger.debug("Neither XML 'id' nor 'name' specified - " + "using generated bean name [" + beanName + "]"); } } catch (Exception ex) { error(ex.getMessage(), ele); return null; } } String[] aliasesArray = StringUtils.toStringArray(aliases); return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); } // 当解析出错时,返回null return null; }
BeanDefinitionParserDelegate.java
/** * 详细对元素中配置的Bean定义的其他的属性进行解析 * 由于上面的方法已经对Bean的id,name和别名属性进行了处理 * 该方法主要是处理除了这三个以外的其他的属性 * 【注意】在解析元素的过程中没有创建和实例化对象,只是创建了Bean元素的定义类BeanDefinition,将元素中的信息 * 设置到了BeanDefinition中作为记录,当依赖注入时才使用这些记录信息创建和实例化具体的Bean对象 * 在对一些配置(如meta,qualifier等)的解析,我们在Spring中使用得不多,在使用Spring元素时,配置最多的就是子元素 */ public AbstractBeanDefinition parseBeanDefinitionElement( Element ele, String beanName, BeanDefinition containingBean) { // 记录解析元素 this.parseState.push(new BeanEntry(beanName)); // 这里只读取元素中配置的class名字,然后载入BeanDefinition中 // 只是记录配置的class名字,不做实例化,对象的实例化在依赖注入的时候完成 String className = null; if (ele.hasAttribute(CLASS_ATTRIBUTE)) { className = ele.getAttribute(CLASS_ATTRIBUTE).trim(); } try { String parent = null; // 如果<bean>元素中配置了parent属性,则获取 parent属性的值 if (ele.hasAttribute(PARENT_ATTRIBUTE)) { parent = ele.getAttribute(PARENT_ATTRIBUTE); } // 根据<bean>元素配置的class名称和parent属性值创建BeanDefinition // 为载入的Bean定义信息做准备 AbstractBeanDefinition bd = createBeanDefinition(className, parent); // 对当前的<bean>元素中配置的一些属性进行解析和设置,如果配置了单态(singleton)属性等 parseBeanDefinitionAttributes(ele, beanName, containingBean, bd); // 为<bean>元素解析的Bean设备描述信息 bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT)); // 为<bean>元素的meta(元信息进行解析) parseMetaElements(ele, bd); // 为<bean>元素的lookup-Method属性进行解析 parseLookupOverrideSubElements(ele, bd.getMethodOverrides()); // 为<bean>元素的replaced-Method属性进行解析 parseReplacedMethodSubElements(ele, bd.getMethodOverrides()); //解析<bean>元素构造方法设置 parseConstructorArgElements(ele, bd); //解析<bean>元素的设置 parsePropertyElements(ele, bd); // 解析<bean>元素的qualifier属性 parseQualifierElements(ele, bd); // 为当前的解析了Bean设置所需要的资源和依赖对象 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(); } // 当前解析元素出错时,返回null return null; }
BeanDefinitionParserDelegate.java
public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName, BeanDefinition containingBean, AbstractBeanDefinition bd) { // 解析scope 属性 if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) { error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele); } else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) { bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE)); } else if (containingBean != null) { // 在嵌入beanDefinition的情况下且没有单独指定scope的属性则使用父类默认的 bd.setScope(containingBean.getScope()); } //解析abstract属性 if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) { bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE))); } // 解析lazy-init属性 String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE); if (DEFAULT_VALUE.equals(lazyInit)) { lazyInit = this.defaults.getLazyInit(); } //若没有设置或者设置其他的字符会被设置为false bd.setLazyInit(TRUE_VALUE.equals(lazyInit)); //解析autowire属性 String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE); bd.setAutowireMode(getAutowireMode(autowire)); // 解析dependency-check属性 String dependencyCheck = ele.getAttribute(DEPENDENCY_CHECK_ATTRIBUTE); bd.setDependencyCheck(getDependencyCheck(dependencyCheck)); //解析depends-on属性 if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) { String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE); bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS)); } //解析autowire-candidate属性 String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE); if ("".equals(autowireCandidate) || DEFAULT_VALUE.equals(autowireCandidate)) { String candidatePattern = this.defaults.getAutowireCandidates(); if (candidatePattern != null) { String[] patterns = StringUtils.commaDelimitedListToStringArray(candidatePattern); bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName)); } } else { bd.setAutowireCandidate(TRUE_VALUE.equals(autowireCandidate)); } //解析primary属性 if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) { bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE))); } //解析init-method属性 if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) { String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE); if (!"".equals(initMethodName)) { bd.setInitMethodName(initMethodName); } } else { if (this.defaults.getInitMethod() != null) { bd.setInitMethodName(this.defaults.getInitMethod()); bd.setEnforceInitMethod(false); } } //解析destroy-method属性 if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) { String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE); bd.setDestroyMethodName(destroyMethodName); } else { if (this.defaults.getDestroyMethod() != null) { bd.setDestroyMethodName(this.defaults.getDestroyMethod()); bd.setEnforceDestroyMethod(false); } } // 解析factory-method属性 if (ele.hasAttribute("factory-method")) { bd.setFactoryMethodName(ele.getAttribute("factory-method")); } // 解析factory-bean属性 if (ele.hasAttribute("factory-bean")) { bd.setFactoryBeanName(ele.getAttribute("factory-bean")); } return bd; }
BeanDefinitionParserDelegate.java
/** * 那么让我们来看具体的XML解析过程 */ public void parseConstructorArgElements(Element beanEle, BeanDefinition bd) { NodeList nl = beanEle.getChildNodes(); for (int i = 0; i < nl.getLength(); i++) { Node node = nl.item(i); if (isCandidateElement(node) && nodeNameEquals(node, CONSTRUCTOR_ARG_ELEMENT)) { parseConstructorArgElement((Element) node, bd); } } }
BeanDefinitionParserDelegate.java
/** * Parse a constructor-arg element. * 这个代码看起来复杂,但是涉及的逻辑其实并不复杂,首先是提取constructor-arg上必要的属性(index,type,name) * 如果配置中指定的index属性,那么操作步骤如下 * 1.解析Constructor-arg的子元素 * 2.使用ConstructorArgumentValues.ValueHolder类型来封装解析出来的元素 * 3.将type,name和index属性一并封装在ConstructorArgumentValues.ValueHolder类型中并添加至当前的BeanDefinition的ConstructorArgumentValues * 的indexedArgumentValues属性中 * * 如果没有指定index属性,那么操作步骤如下: * 1.解析constructor-arg的子元素 * 2.使用ConstructorArgumentValues.ValueHolder类型来封装解析出来的元素 * 3.将type,name和index属性一并封装在ConstructorArgumentValues.ValueHolder类型中并添加至当前的BeanDefinition的ConstructorArgumentValues * 的genericArgumentValues属性中 * 可以看到,对于是否制定的index属性来讲,Spring处理流程是不同的,关键在于属性信息被保存的位置 * 那么整个流程后,我们尝试着进一步了解解析构造函数配置中子元素的过程,进入parsePropertyValue: */ public void parseConstructorArgElement(Element ele, BeanDefinition bd) { // 提取index 属性 String indexAttr = ele.getAttribute(INDEX_ATTRIBUTE); // 提取type属性 String typeAttr = ele.getAttribute(TYPE_ATTRIBUTE); // 提取name属性 String nameAttr = ele.getAttribute(NAME_ATTRIBUTE); if (StringUtils.hasLength(indexAttr)) { try { /** * 6.解析子元素constructor-arg * 对构造函数是是非常常用的,同时也是非常复杂的,也相信大家对构造函数的配置都不陌生 ,举个简单的例子来说 * ... * <beans> * <!--默认的情况下是按照参数的顺序注入的,当指定的index索引后就可以改变了--> * <bean id="helloBean" class="com.HelloBean"> * <constructor-arg index = "0"> * <value>郝佳 * </constructor-arg> * <constructor-arg index="1"> * <value>你好 * </constructor-arg> * </bean> * </beans> * 上面的配置是Spring构造函数配置中最佳的基础配置,实现功能就是对HelloBean自动寻找对的函数,并在初始化的时候将设置参数传入进去 */ int index = Integer.parseInt(indexAttr); if (index < 0) { error("'index' cannot be lower than 0", ele); } else { try { this.parseState.push(new ConstructorArgumentEntry(index)); // 解析ele对应的属性元素 Object value = parsePropertyValue(ele, bd, null); ConstructorArgumentValues.ValueHolder valueHolder = new ConstructorArgumentValues.ValueHolder(value); if (StringUtils.hasLength(typeAttr)) { valueHolder.setType(typeAttr); } if (StringUtils.hasLength(nameAttr)) { valueHolder.setName(nameAttr); } valueHolder.setSource(extractSource(ele)); // 不允许重复指定相同的参数 if (bd.getConstructorArgumentValues().hasIndexedArgumentValue(index)) { error("Ambiguous constructor-arg entries for index " + index, ele); } else { bd.getConstructorArgumentValues().addIndexedArgumentValue(index, valueHolder); } } finally { this.parseState.pop(); } } } catch (NumberFormatException ex) { error("Attribute 'index' of tag 'constructor-arg' must be an integer", ele); } } else { // 如果没有index属性则忽略去属性,自动寻找 /** <bean id="user" class="com.spring_1_100.test_41_50.test41.User"> <constructor-arg value="2"> <constructor-arg value="1"> </bean> */ try { this.parseState.push(new ConstructorArgumentEntry()); Object value = parsePropertyValue(ele, bd, null); ConstructorArgumentValues.ValueHolder valueHolder = new ConstructorArgumentValues.ValueHolder(value); if (StringUtils.hasLength(typeAttr)) { valueHolder.setType(typeAttr); } if (StringUtils.hasLength(nameAttr)) { valueHolder.setName(nameAttr); } valueHolder.setSource(extractSource(ele)); bd.getConstructorArgumentValues().addGenericArgumentValue(valueHolder); } finally { this.parseState.pop(); } } }
BeanDefinitionParserDelegate.java
/** * 解析获取元素的值 * 通过下面的源码解析,我们了解了Spring配置文件中的元素中的子元素的相关配置, * 1.ref 被封装成指向依赖对象的一个引用 * 2.value 被封装成一个字符串类型的对象 * 3.ref 和value都是通过解析数据类型属性值.setSource(extractSource(ele));将方法的属性或者引用与引用属性关系起来 * 最后元素的子元素通过parsePropertySubElement()方法解析,下面我们继续分析该方法的源码,了解其解析过程 * * 从代码上来看,对函数的属性元素的解析,经历了以下的几个过程 * 1.略过description或者meta * 2.提取constructor-arg上的ref和value属性,以便于根据规则验证正确性,其规则为在constructor-arg 上不存在以下的情况 * 同时既有ref又有value属性 * 存在ref属性或者value属性且又有子元素 * 3.ref属性的处理,使用RunTimeBeanReference封装对应的ref名称,如: * <constructor-arg ref="a"> * * </constructor-arg> * 4.value属性的处理,使用TypeStringValue封装,如: * <constructor-arg value="a"> * 5.子元素的处理 * <constructor-arg > * <map> * <entry key="key" value="value"> * </map> * </constructor-arg> * 而对于子元素的处理,例如,这里反映到的在构造函数中嵌入了子元素map是怎样实现的呢?parsePropertySubElement中对实现了对各种子元素的处理 */ public Object parsePropertyValue(Element ele, BeanDefinition bd, String propertyName) { String elementName = (propertyName != null) ? " element for property '" + propertyName + "'" : " element"; // 获取中的所有的子元素,只能是ref,value,list,etc中的一种类型 NodeList nl = ele.getChildNodes(); Element subElement = null; for (int i = 0; i < nl.getLength(); i++) { Node node = nl.item(i); // 子元素是description和meta属性 不做处理 if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT) && !nodeNameEquals(node, META_ELEMENT)) { if (subElement != null) { error(elementName + " must not contain more than one sub-element", ele); } else { // 当property元素包含子元素 subElement = (Element) node; } } } // 解析constructor-arg 的ref 属性 boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE); // 解析constructor-arg 上的value属性 boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE); // 判断属性值是ref还是value,不允许既是ref 又是value if ((hasRefAttribute && hasValueAttribute) || ((hasRefAttribute || hasValueAttribute) && subElement != null)) { /** * 在constructor-arg上不存在: * 1.同时既有ref属性又有value属性 * 2.存在ref属性或者value属性且又有子元素 */ error(elementName + " is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element", ele); } // 如果属性值是ref ,创建一个ref 的数据对象,RuntimeBeanReference,这个对象封装了ref if (hasRefAttribute) { String refName = ele.getAttribute(REF_ATTRIBUTE); if (!StringUtils.hasText(refName)) { error(elementName + " contains empty 'ref' attribute", ele); } //一个指向运行是所依赖对象的引用 ,ref属性的处理,使用RuntimeBeanReference封装对应的ref名称 RuntimeBeanReference ref = new RuntimeBeanReference(refName); ref.setSource(extractSource(ele)); return ref; // 如果属性值是value,创建一个value数据对象,typedStringValue,这个对象封装了value } else if (hasValueAttribute) { // 一个持有String类型的对象 TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE)); // 设置这个value的数据对象被当前对象所引用 valueHolder.setSource(extractSource(ele)); return valueHolder; } else if (subElement != null) { // 解析子元素 return parsePropertySubElement(subElement, bd); } else { // 属性值既不是ref也不是value,解析出错,返回null error(elementName + " must specify a ref or value", ele); return null; } }
通过上面的解析,我们得到,将factory-method属性值保存到factoryMethodName中,将factory-bean属性值保存到factoryBeanName中,将构造函数参数保存到genericArgumentValues属性中。
我们再来看看bean的创建过程
AbstractAutowireCapableBeanFactory.java
/** * 在CreateBeanInstance()方法中,根据指定的初始化策略,使用了简单的工厂,工厂方法或者容器的自动装配生成java实例对象,创建对象的代码如下 * 创建Bean的实例对象 * * 虽然代码中实例化的细节非常的复杂,但是存在 createBeanInstance 方法中我人还是可以清晰的看到实例化的逻辑 * 1.如果在 如果 RootBeanDefinition 中存在 facotryMethodName 属性,或者说在配置文件中配置了 factory-method,那么 Spring * 会尝试使用 instantiateusingFactoryMethod(beanName,mbd,args) 方法根据 RootBeanDefinition 中的配置生成 bean 的实例 * 2.解析构造函数并在构造函数的实例化,因为一个 bean 对应的类中可能会有多个构造函数,而每个构造函数的参数不同,Spring 在根据参数及类型去判断最终会使用哪个 * 构造函数进行实例化,但是判断的过程是个比较消耗性能的步骤,所以采用缓存机制 ,如果已经解析过,则不需要重复解析而是直接从 * rootBeanDefinition 中的属性 resolvedConstructorOrFactoryMethod 缓存的值去取,否则需要再次解析,并将解析的结果添加至 RootBeanDefinition * 中的属性 resolvedConstructorOrFactoryMethod 中 */ protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) { // Make sure bean class is actually resolved at this point. // 确认Bean是可实例化的, // 解析 class Class<?> beanClass = resolveBeanClass(mbd, beanName); // 使用工厂方法对Bean进行实例化, // getModifiers 得到的就是 前面的 的修饰符 ,这个方法 字段和方法 都有。这个方法的值是 修饰符 相加的到的值。 /** * public class Test1 { * * String c; * public String a; * private String b; * protected String d; * static String e; * final String f="f"; * * } * * Field[] fields = Test1.class.getDeclaredFields(); * for( Field field: fields) { * System.out.println( field.getName() +":" + field.getModifiers() ); * } * c:0 * a:1 * b:2 * d:4 * e:8 * f:16 */ // 所以:什么都不加 是0 , public 是1 ,private 是 2 ,protected 是 4,static 是 8 ,final 是 16。 if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Bean class isn't public, and non-public access not allowed: " + beanClass.getName()); } // 如果工厂方法不不为空,则使用工厂方法初始化策略 if (mbd.getFactoryMethodName() != null) { // 调用工厂方法进行实例化 return instantiateUsingFactoryMethod(beanName, mbd, args); } // 使用容器的自动装配方法进行实例化 boolean resolved = false; boolean autowireNecessary = false; if (args == null) { synchronized (mbd.constructorArgumentLock) { // 一个类有多个构造函数都有不同的参数,所以调用需要根据参数锁定构造函数或者对应的工厂方法 | 一个类有多个构造函数,每个构造函数都有不同的参数, // 所以调用前需要先根据参数锁定构造函数或者工厂方法 if (mbd.resolvedConstructorOrFactoryMethod != null) { resolved = true; autowireNecessary = mbd.constructorArgumentsResolved; } } } // 如果已经解析过,则使用解析好的构造函数方法不需要再次锁定 if (resolved) { if (autowireNecessary) { // 配置了自动装配属性,使用了容器的自动装配进行实例化 //容器的自动装配根据参数的类型匹配Bean的构造方法 return autowireConstructor(beanName, mbd, null, null); } else { // 使用了默认无参构造方法进行实例化 return instantiateBean(beanName, mbd); } } // Need to determine the constructor... // 使用了Bean的构造方法进行实例化 Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); if (ctors != null || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { // 使用了容器的自动装配特性,调用匹配的构造方法进行实例化 ,构造函数自动注入 ,带参数实例化,带有参数实例化的过程相当的复杂,因为存在不确定性。 return autowireConstructor(beanName, mbd, ctors, args); } // No special handling: simply use no-arg constructor. // 使用了默认的无参的构造方法进行实例化 return instantiateBean(beanName, mbd); }
AbstractAutowireCapableBeanFactory.java
protected BeanWrapper instantiateUsingFactoryMethod( String beanName, RootBeanDefinition mbd, Object[] explicitArgs) { return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs); }
ConstructorResolver.java
public BeanWrapper instantiateUsingFactoryMethod( final String beanName, final RootBeanDefinition mbd, final Object[] explicitArgs) { BeanWrapperImpl bw = new BeanWrapperImpl(); this.beanFactory.initBeanWrapper(bw); Object factoryBean; Class<?> factoryClass; boolean isStatic; String factoryBeanName = mbd.getFactoryBeanName(); if (factoryBeanName != null) { if (factoryBeanName.equals(beanName)) { throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName, "factory-bean reference points back to the same bean definition"); } //获取到工厂方法factoryBean factoryBean = this.beanFactory.getBean(factoryBeanName); if (factoryBean == null) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "factory-bean '" + factoryBeanName + "' (or a BeanPostProcessor involved) returned null"); } if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) { throw new IllegalStateException("About-to-be-created singleton instance implicitly appeared " + "through the creation of the factory bean that its bean definition points to"); } factoryClass = factoryBean.getClass(); isStatic = false; } else { // It's a static factory method on the bean class. if (!mbd.hasBeanClass()) { throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName, "bean definition declares neither a bean class nor a factory-bean reference"); } factoryBean = null; factoryClass = mbd.getBeanClass(); isStatic = true; } Method factoryMethodToUse = null; ArgumentsHolder argsHolderToUse = null; Object[] argsToUse = null; if (explicitArgs != null) { argsToUse = explicitArgs; } else { Object[] argsToResolve = null; synchronized (mbd.constructorArgumentLock) { factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod; if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) { // Found a cached factory method... argsToUse = mbd.resolvedConstructorArguments; if (argsToUse == null) { argsToResolve = mbd.preparedConstructorArguments; } } } if (argsToResolve != null) { argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve); } } if (factoryMethodToUse == null || argsToUse == null) { // Need to determine the factory method... // Try all methods with this name to see if they match the given arguments. factoryClass = ClassUtils.getUserClass(factoryClass); //获取到所有的候选方法 Method[] rawCandidates = getCandidateMethods(factoryClass, mbd); List<Method> candidateSet = new ArrayList(); for (Method candidate : rawCandidates) { //取出和工厂方法名称相同的方法保存到候选方法中 if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) { candidateSet.add(candidate); } } Method[] candidates = candidateSet.toArray(new Method[candidateSet.size()]); AutowireUtils.sortFactoryMethods(candidates); ConstructorArgumentValues resolvedValues = null; //取出和工厂方法名称相同的方法保存到候选方法中 boolean autowiring = (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR); int minTypeDiffWeight = Integer.MAX_VALUE; Set<Method> ambiguousFactoryMethods = null; int minNrOfArgs; if (explicitArgs != null) { minNrOfArgs = explicitArgs.length; } else { // We don't have arguments passed in programmatically, so we need to resolve the // arguments specified in the constructor arguments held in the bean definition. ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues(); resolvedValues = new ConstructorArgumentValues(); minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues); } List<Exception> causes = null; for (int i = 0; i < candidates.length; i++) { Method candidate = candidates[i]; //获取候选方法的参数类型 Class<?>[] paramTypes = candidate.getParameterTypes(); if (paramTypes.length >= minNrOfArgs) { ArgumentsHolder argsHolder; if (resolvedValues != null) { // Resolved constructor arguments: type conversion and/or autowiring necessary. try { String[] paramNames = null; ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer(); if (pnd != null) { //获取参数名 {"stuId"} paramNames = pnd.getParameterNames(candidate); } //创建构造函数参数持有者 argsHolder = createArgumentArray( beanName, mbd, resolvedValues, bw, paramTypes, paramNames, candidate, autowiring); } catch (UnsatisfiedDependencyException ex) { if (this.beanFactory.logger.isTraceEnabled()) { this.beanFactory.logger.trace("Ignoring factory method [" + candidate + "] of bean '" + beanName + "': " + ex); } if (i == candidates.length - 1 && argsHolderToUse == null) { if (causes != null) { for (Exception cause : causes) { this.beanFactory.onSuppressedException(cause); } } throw ex; } else { // Swallow and try next overloaded factory method. if (causes == null) { causes = new LinkedList(); } causes.add(ex); continue; } } } else { // Explicit arguments given -> arguments length must match exactly. if (paramTypes.length != explicitArgs.length) { continue; } argsHolder = new ArgumentsHolder(explicitArgs); } int typeDiffWeight = (mbd.isLenientConstructorResolution() ? argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes)); // 根据方法参数的权重匹配出最合适的方法及参数 if (typeDiffWeight < minTypeDiffWeight) { factoryMethodToUse = candidate; argsHolderToUse = argsHolder; argsToUse = argsHolder.arguments; minTypeDiffWeight = typeDiffWeight; ambiguousFactoryMethods = null; } // Find out about ambiguity: In case of the same type difference weight // for methods with the same number of parameters, collect such candidates // and eventually raise an ambiguity exception. // However, only perform that check in non-lenient constructor resolution mode, // and explicitly ignore overridden methods (with the same parameter signature). else if (factoryMethodToUse != null && typeDiffWeight == minTypeDiffWeight && !mbd.isLenientConstructorResolution() && paramTypes.length == factoryMethodToUse.getParameterTypes().length && !Arrays.equals(paramTypes, factoryMethodToUse.getParameterTypes())) { if (ambiguousFactoryMethods == null) { ambiguousFactoryMethods = new LinkedHashSet(); ambiguousFactoryMethods.add(factoryMethodToUse); } ambiguousFactoryMethods.add(candidate); } } } if (factoryMethodToUse == null) { List argTypes = new ArrayList(minNrOfArgs); if (explicitArgs != null) { for (Object arg : explicitArgs) { argTypes.add(arg != null ? arg.getClass().getSimpleName() : "null"); } } else { Set valueHolders = new LinkedHashSet(resolvedValues.getArgumentCount()); valueHolders.addAll(resolvedValues.getIndexedArgumentValues().values()); valueHolders.addAll(resolvedValues.getGenericArgumentValues()); for (ValueHolder value : valueHolders) { String argType = (value.getType() != null ? ClassUtils.getShortName(value.getType()) : (value.getValue() != null ? value.getValue().getClass().getSimpleName() : "null")); argTypes.add(argType); } } String argDesc = StringUtils.collectionToCommaDelimitedString(argTypes); throw new BeanCreationException(mbd.getResourceDescription(), beanName, "No matching factory method found: " + (mbd.getFactoryBeanName() != null ? "factory bean '" + mbd.getFactoryBeanName() + "'; " : "") + "factory method '" + mbd.getFactoryMethodName() + "(" + argDesc + ")'. " + "Check that a method with the specified name " + (minNrOfArgs > 0 ? "and arguments " : "") + "exists and that it is " + (isStatic ? "static" : "non-static") + "."); } else if (void.class == factoryMethodToUse.getReturnType()) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid factory method '" + mbd.getFactoryMethodName() + "': needs to have a non-void return type!"); } else if (ambiguousFactoryMethods != null) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Ambiguous factory method matches found in bean '" + beanName + "' " + "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " + ambiguousFactoryMethods); } if (explicitArgs == null && argsHolderToUse != null) { argsHolderToUse.storeCache(mbd, factoryMethodToUse); } } try { Object beanInstance; if (System.getSecurityManager() != null) { final Object fb = factoryBean; final Method factoryMethod = factoryMethodToUse; final Object[] args = argsToUse; beanInstance = AccessController.doPrivileged(new PrivilegedAction() { @Override public Object run() { return beanFactory.getInstantiationStrategy().instantiate( mbd, beanName, beanFactory, fb, factoryMethod, args); } }, beanFactory.getAccessControlContext()); } else { //我们得到了工厂bean,方法,及方法参数,从而通过反射来调用工厂方法,从而获取相应的bean对象 beanInstance = this.beanFactory.getInstantiationStrategy().instantiate( mbd, beanName, this.beanFactory, factoryBean, factoryMethodToUse, argsToUse); } if (beanInstance == null) { return null; } bw.setWrappedInstance(beanInstance); return bw; } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Bean instantiation via factory method failed", ex); } }
ConstructorResolver.java
private int resolveConstructorArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw, ConstructorArgumentValues cargs, ConstructorArgumentValues resolvedValues) { TypeConverter converter = (this.beanFactory.getCustomTypeConverter() != null ? this.beanFactory.getCustomTypeConverter() : bw); BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter); int minNrOfArgs = cargs.getArgumentCount(); for (Map.Entry<Integer, ConstructorArgumentValues.ValueHolder> entry : cargs.getIndexedArgumentValues().entrySet()) { int index = entry.getKey(); if (index < 0) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid constructor argument index: " + index); } if (index > minNrOfArgs) { minNrOfArgs = index + 1; } ConstructorArgumentValues.ValueHolder valueHolder = entry.getValue(); if (valueHolder.isConverted()) { resolvedValues.addIndexedArgumentValue(index, valueHolder); } else { Object resolvedValue = valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue()); ConstructorArgumentValues.ValueHolder resolvedValueHolder = new ConstructorArgumentValues.ValueHolder(resolvedValue, valueHolder.getType(), valueHolder.getName()); resolvedValueHolder.setSource(valueHolder); resolvedValues.addIndexedArgumentValue(index, resolvedValueHolder); } } for (ConstructorArgumentValues.ValueHolder valueHolder : cargs.getGenericArgumentValues()) { if (valueHolder.isConverted()) { resolvedValues.addGenericArgumentValue(valueHolder); } else { Object resolvedValue = //得到转化后的值 valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue()); ConstructorArgumentValues.ValueHolder resolvedValueHolder = new ConstructorArgumentValues.ValueHolder(resolvedValue, valueHolder.getType(), valueHolder.getName()); resolvedValueHolder.setSource(valueHolder); //将constructor-arg 的 value 值,保存到resolvedValues当中 resolvedValues.addGenericArgumentValue(resolvedValueHolder); } } return minNrOfArgs; }
SimpleInstantiationStrategy.java
public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner, Object factoryBean, final Method factoryMethod, Object... args) { try { if (System.getSecurityManager() != null) { AccessController.doPrivileged(new PrivilegedAction() { @Override public Object run() { ReflectionUtils.makeAccessible(factoryMethod); return null; } }); } else { ReflectionUtils.makeAccessible(factoryMethod); } Method priorInvokedFactoryMethod = currentlyInvokedFactoryMethod.get(); try { currentlyInvokedFactoryMethod.set(factoryMethod); //通过反射获取bean对象 return factoryMethod.invoke(factoryBean, args); } finally { if (priorInvokedFactoryMethod != null) { currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod); } else { currentlyInvokedFactoryMethod.remove(); } } } catch (IllegalArgumentException ex) { throw new BeanInstantiationException(factoryMethod.getReturnType(), "Illegal arguments to factory method '" + factoryMethod.getName() + "'; " + "args: " + StringUtils.arrayToCommaDelimitedString(args), ex); } catch (IllegalAccessException ex) { throw new BeanInstantiationException(factoryMethod.getReturnType(), "Cannot access factory method '" + factoryMethod.getName() + "'; is it public?", ex); } catch (InvocationTargetException ex) { String msg = "Factory method '" + factoryMethod.getName() + "' threw exception"; if (bd.getFactoryBeanName() != null && owner instanceof ConfigurableBeanFactory && ((ConfigurableBeanFactory) owner).isCurrentlyInCreation(bd.getFactoryBeanName())) { msg = "Circular reference involving containing bean '" + bd.getFactoryBeanName() + "' - consider " + "declaring the factory method as static for independence from its containing instance. " + msg; } throw new BeanInstantiationException(factoryMethod.getReturnType(), msg, ex.getTargetException()); } }
代码分析到这里己经感觉非常的简单了,我们来总结一下。
1.将xml中的属性factory-bean和factory-method保存到BeanDefinition相应的属性中,将constructor-arg的参数值保存到ConstructorArgumentValues的genericArgumentValues集合中。
2.当有工厂方法名时,调用instantiateUsingFactoryMethod这个方法来实例化bean .
3.在这个instantiateUsingFactoryMethod方法中主要通过方法名,方法参数个数,方法参数名称,以及方法参数类型,找出最匹配的工厂方法。
4.通过反射调用工厂方法得到实例。
5.将实例保存到容器的singletonObjects中。
本文的github地址
https://github.com/quyixiao/spring_tiny/tree/master/src/main/java/com/spring_1_100/test_41_50/test50