首先获取到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
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
�继续往下看:
解析其它的属性:
默认不是自动装配。相关代码如下:
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: 通过构造器注入
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>
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
primary 优先级高的bean
init-method 用于在bean初始化时指定执行方法;
相关链接:https://blog.csdn.net/jmkmlm123456/article/details/102455056
destroy-method 销毁配置的标签解析;
factory-method和factory-bean标签解析
相关链接:https://www.cnblogs.com/sharpest/p/7784097.html
之后解析bean的decription子元素:
<bean id="b" name="one, two" class="base.SimpleBean">
<description>SimpleBeandescription>
bean>
就仅仅是个描述。
然后是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。
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方式实现依赖注入
此标签用于替换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。
构造参数(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
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实现)。
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标签的解析告一段落。