8.Spring源码解析-parseBeanDefinitionElement bean解析

8.Spring源码解析-parseBeanDefinitionElement bean解析_第1张图片
8.Spring源码解析-parseBeanDefinitionElement bean解析_第2张图片
首先获取到bean的class属性和parent属性,配置了parent之后,当前bean会继承父bean的属性。之后根据class和parent创建BeanDefinition对象。相关代码区域如下:

String className = null;
if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
    className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
}
String parent = null;
if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
    parent = ele.getAttribute(PARENT_ATTRIBUTE);
}
AbstractBeanDefinition bd = createBeanDefinition(className, parent);

创建createBeanDefinition
8.Spring源码解析-parseBeanDefinitionElement bean解析_第3张图片
BeanDefinition的创建在BeanDefinitionReaderUtils.createBeanDefinition:

public static AbstractBeanDefinition createBeanDefinition(
        String parentName, String className, ClassLoader classLoader) {
    GenericBeanDefinition bd = new GenericBeanDefinition();
    bd.setParentName(parentName);
    if (className != null) {
        if (classLoader != null) {
            bd.setBeanClass(ClassUtils.forName(className, classLoader));
        }
        else {
            bd.setBeanClassName(className);
        }
    }
    return bd;
}

创建AbstractBeanDefinition是先创建它的子类GenericBeanDefinition并设置好parentName和className
�继续往下看:
解析其它的属性:
8.Spring源码解析-parseBeanDefinitionElement bean解析_第4张图片
8.Spring源码解析-parseBeanDefinitionElement bean解析_第5张图片
8.Spring源码解析-parseBeanDefinitionElement bean解析_第6张图片
默认不是自动装配。相关代码如下:

public int getAutowireMode(String attValue) {
		String att = attValue;
		if (DEFAULT_VALUE.equals(att)) {
			att = this.defaults.getAutowire();
		}
		int autowire = AbstractBeanDefinition.AUTOWIRE_NO;
		if (AUTOWIRE_BY_NAME_VALUE.equals(att)) {
			autowire = AbstractBeanDefinition.AUTOWIRE_BY_NAME;
		}
		else if (AUTOWIRE_BY_TYPE_VALUE.equals(att)) {
			autowire = AbstractBeanDefinition.AUTOWIRE_BY_TYPE;
		}
		else if (AUTOWIRE_CONSTRUCTOR_VALUE.equals(att)) {
			autowire = AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR;
		}
		else if (AUTOWIRE_AUTODETECT_VALUE.equals(att)) {
			autowire = AbstractBeanDefinition.AUTOWIRE_AUTODETECT;
		}
		// Else leave default value.
		return autowire;
	}

AutowireMode(自动装配模型):在spring中有常用四种模式分别是:
1 autowire_no(0): 默认装配模式, 目前非xml配置都是使用这种方式,然后程序员使用注解手动注入
2 autowire_name: 通过set方法,并且 set方法的名称需要和bean的name一致 byName
3 autowire_type: 通过set方法,并且再根据bean的类型,注入属性,是通过类型配置 byType
4 autowire_construcor: 通过构造器注入


image.png
depends-on标签解析。
depend-on用来表示一个Bean的实例化依靠另一个Bean先实例化。如果在一个bean A上定义了depend-on B那么就表示:A 实例化前先实例化 B。示例如下:



DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
  <bean name="dao" class="research.spring.beanfactory.ch3.Dao" depends-on="database">
  bean>
  <bean id="database" class="research.spring.beanfactory.ch3.Database">
  bean>   
beans>

8.Spring源码解析-parseBeanDefinitionElement bean解析_第7张图片
autowire-candidate标签解析
autowire-candidate:设置当前bean在被其他对象作为自动注入对象的时候,是否作为候选bean,默认值是true。
例子配置:


<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-4.3.xsd">
 
    <bean id="serviceA" class="com.javacode2018.lesson001.demo9.SetterBean$ServiceA" autowire-candidate="false"/>
    <bean id="serviceB" class="com.javacode2018.lesson001.demo9.SetterBean$ServiceB"/>
 
    <bean id="setterBean" class="com.javacode2018.lesson001.demo9.SetterBean" autowire="byType" />
beans>

相关链接:https://blog.csdn.net/chenzoff/article/details/124103570
8.Spring源码解析-parseBeanDefinitionElement bean解析_第8张图片
primary 优先级高的bean
8.Spring源码解析-parseBeanDefinitionElement bean解析_第9张图片
init-method 用于在bean初始化时指定执行方法;
相关链接:https://blog.csdn.net/jmkmlm123456/article/details/102455056
8.Spring源码解析-parseBeanDefinitionElement bean解析_第10张图片
destroy-method 销毁配置的标签解析;

8.Spring源码解析-parseBeanDefinitionElement bean解析_第11张图片
factory-method和factory-bean标签解析
相关链接:https://www.cnblogs.com/sharpest/p/7784097.html
8.Spring源码解析-parseBeanDefinitionElement bean解析_第12张图片
之后解析bean的decription子元素:

<bean id="b" name="one, two" class="base.SimpleBean">     
  <description>SimpleBeandescription> 
bean>

就仅仅是个描述。
8.Spring源码解析-parseBeanDefinitionElement bean解析_第13张图片
然后是meta子元素的解析,meta元素在xml配置文件里是这样的:

<bean id="b" name="one, two" class="base.SimpleBean">
    <meta key="name" value="skywalker"/>
bean>

相关代码:

public void parseMetaElements(Element ele, BeanMetadataAttributeAccessor attributeAccessor) {
    NodeList nl = ele.getChildNodes();
    for (int i = 0; i < nl.getLength(); i++) {
        Node node = nl.item(i);
        if (isCandidateElement(node) && nodeNameEquals(node, META_ELEMENT)) {
            Element metaElement = (Element) node;
            String key = metaElement.getAttribute(KEY_ATTRIBUTE);
            String value = metaElement.getAttribute(VALUE_ATTRIBUTE);
            //就是一个key, value的载体,无他
            BeanMetadataAttribute attribute = new BeanMetadataAttribute(key, value);
            //sourceExtractor默认是NullSourceExtractor,返回的是空
            attribute.setSource(extractSource(metaElement));
            attributeAccessor.addMetadataAttribute(attribute);
        }
    }
}

AbstractBeanDefinition继承自BeanMetadataAttributeAccessor类,底层使用了一个LinkedHashMap保存metadata。
8.Spring源码解析-parseBeanDefinitionElement bean解析_第14张图片
lookup-method解析:
此标签的作用在于当一个bean的某个方法被设置为lookup-method后,每次调用此方法时,都会返回一个新的指定bean的对象。用法示例:

<bean id="apple" class="cn.com.willchen.test.di.Apple" scope="prototype"/>

<bean id="fruitPlate" class="cn.com.willchen.test.di.FruitPlate">
  <lookup-method name="getFruit" bean="apple"/>
bean>

数据保存在Set中,对应的类是MethodOverrides。可以参考:
Spring - lookup-method方式实现依赖注入
8.Spring源码解析-parseBeanDefinitionElement bean解析_第15张图片
此标签用于替换bean里面的特定的方法实现,替换者必须实现Spring的MethodReplacer接口,有点像aop的意思。
配置文件示例:

<bean name="replacer" class="springroad.deomo.chap4.MethodReplace" />  
<bean name="testBean" class="springroad.deomo.chap4.LookupMethodBean">
    <replaced-method name="test" replacer="replacer">
        <arg-type match="String" />
    replaced-method>  
bean> 

arg-type的作用是指定替换方法的参数类型,因为接口的定义参数都是Object的。参考: SPRING.NET 1.3.2 学习20–方法注入之替换方法注入
解析之后将数据放在ReplaceOverride对象中,里面有一个LinkedList专门用于保存arg-type。
8.Spring源码解析-parseBeanDefinitionElement bean解析_第16张图片
构造参数(constructor-arg)解析:
作用一目了然,使用示例:

<bean class="base.SimpleBean">
    <constructor-arg>
        <value type="java.lang.String">Catvalue>
    constructor-arg>
bean>

type一般不需要指定,除了泛型集合那种。除此之外,constructor-arg还支持name, index, ref等属性,可以具体的指定参数的位置等。构造参数解析后保存在BeanDefinition内部一个ConstructorArgumentValues对象中。如果设置了index属性,那么以Map的形式保存,反之,以List的形式保存。
8.Spring源码解析-parseBeanDefinitionElement bean解析_第17张图片
property解析:
非常常用的标签,用以为bean的属性赋值,支持value和ref两种形式,示例:

<bean class="base.SimpleBean">
    <property name="name" value="skywalker" />
bean>

value和ref属性不能同时出现,如果是ref,那么将其值保存在不可变的RuntimeBeanReference对象中,其实现了BeanReference接口,此接口只有一个getBeanName方法。如果是value,那么将其值保存在TypedStringValue对象中。最终将对象保存在BeanDefinition内部一个MutablePropertyValues对象中(内部以ArrayList实现)。
8.Spring源码解析-parseBeanDefinitionElement bean解析_第18张图片

qualifier解析:
配置例子:

<bean class="base.Student">
    <property name="name" value="skywalker">property>
    <property name="age" value="12">property>
    <qualifier type="org.springframework.beans.factory.annotation.Qualifier" value="student" />
bean>	
<bean class="base.Student">
    <property name="name" value="seaswalker">property>
    <property name="age" value="15">property>
    <qualifier value="student_2">qualifier>
bean>
<bean class="base.SimpleBean" />

至此bean标签的解析告一段落。

你可能感兴趣的:(springIOC,spring,java,后端)