Spring —— Bean 解析、注册

Spring XML 解析要完成的任务是将 XML 中的标签解析成 BeanDefinition 注册到 BeanFactory 中。
以 ClassPathXmlApplicationContext 为例,上述工作在 obtainFreshBeanFactory() 中完成,分为:

  1. 创建 BeanFactory
  2. SAX 解析 XML
  3. 标签解析,向容器注册 Bean
    1. 默认标签解析
    2. 自定义标签解析
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

1. 创建 BeanFactory

创建 DefaulListableBeanFactory,并设置 allowBeanDefinitionOverriding、allowCircularRefrences
创建 DefaulListableBeanFactory
设置 allowBeanDefinitionOverriding、allowCircularRefrences

2. SAX 解析 XML

以下面这种方式加载配置文件时,涉及到的对象、类包括:BeanDefinitionReader、configLocations、Resource、InputSource、DocumentBuilderFactory、DocumentBuilder、Document。

ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-context.xml");
  1. 创建 BeanDefinitionReader
    创建 BeanDefinitionReader
  2. 获取 XML 配置文件
    获取 XML 配置文件
  3. 封装成 Resource
    封装成 Resource
  4. 获取流,并封装成 InputSource
    获取流,并封装成 InputSource
  5. SAX 解析
    在这里插入图片描述

3. 标签解析

涉及到的对象、类包括:BeanDefinitionDocumentReader。

  1. 创建 BeanDefinitionDocumentReader
    创建 BeanDefinitionDocumentReader
  2. 分类解析:默认标签、自定义标签。判断标准是:默认标签命名空间是 http://www.springframework.org/schema/beans
    分类解析

3.1 默认标签解析

默认标签包括 import、alias、bean、beans,如下
标签
各标签使用示例:

<import resource="customerContext.xml"/>

<alias name="testBean" alias="testBean,testBean2"/>
   <!-- 给 bean 添加别名还有一种方式,使用 bean 标签 -->
   <bean id="testBean" name="beanName1,beanName2" class="TestBean"/>

<beans>
   <beans> </beans>
</beans>

最重要的是 bean 标签,包括:

  1. 属性:id、name、scope、abstract、lazy-init、autowire、depends-on、autowire-candidate、init-method、destory-method、factory-method、factory-bean
  2. 子标签:lookup-method、replaced-method、constructor-arg、property

下面分析 bean 标签解析步骤:

  1. 创建 GenericBeanDefinition
    创建 GenericBeanDefinition
  2. 解析属性
    属性解析
  3. 解析子标签
    解析子标签
    子标签使用示例:
<!-- lookup-method -->
<bean id="aPeople" class="com.xmustang.bean.APeople" lazy-init="false"></bean>
<bean id="showLookUp" class="com.xmustang.bean.ShowLookUp">
    <lookup-method name="getPeople" bean="aPeople"></lookup-method>
</bean>

public abstract class ShowLookUp {
	public void showName() {
   		getPeople().getName();
	}

	public abstract IPeople getPeople();
}

<!-- replaced-method -->
<bean id="replaceClass" class="com.mustang.bean.ReplaceClass" lazy-init="false"/>
<bean id="originClass" class="com.mustang.bean.OriginClass">
    <replaced-method name="say" replacer="replaceClass">
        <!--方法可能出现重载的情况,要根据类型和方法名找方法-->
        <arg-type match="java.lang.String"/>
    </replaced-method>
</bean>

public class ReplaceClass implements MethodReplacer {
	@Override
	public Object reimplement(Object obj, Method method, Object[] args) {
   		System.out.println("I am replace method-->reimplement!");
   		return null;
	}
}

<!-- constructor-arg -->
<bean class="com.mustang.bean.ConstructorArgBean" id="constructorArgBean">
    <constructor-arg name="username" value="Tom" index="0" type="java.lang.String"/>
    <constructor-arg name="password" value="123" index="1" type="java.lang.String"/>
</bean>

<!-- property -->
<bean class="com.mustang.bean.PropertyBean" id="propertyBean">
    <property name="username" value="Jerry"/>
    <property name="password" value="123"/>
</bean>
  1. BeanDefinition 封装成 BeanDefinitionHolder
    BeanDefinition 封装成 BeanDefinitionHolder
  2. 注册 bean
    注册 bean
    注册 bean、别名
    注册 bean、别名
    相关的容器有:DefaultListableBeanFactory.beanDefinitionMap、DefaultListableBeanFactory.beanDefinitionNames;SimpleAliasRegistry.aliasMap

3.2 默认标签解析

  1. 加载 .handlers 文件,获取所有 NamespaceHandler
    加载 .handlers 文件,获取所有 NamespaceHandler
  2. 根据自定义标签 namespaceUri 获取对应的 NamespaceHandler
    根据自定义标签 namespaceUri 获取对应的 NamespaceHandler
  3. 调用 NamespaceHandler.init() 注册解析器
    调用 NamespaceHandler.init() 注册解析器
  4. 调用解析器的 parse() 解析标签
    调用解析器的 parse() 解析标签

3.2.1 context:component-scan 标签解析

context:component-scan 是自定义标签,它的 NamespaceHandler、BeanDefinitionParser 是 ContextNamespaceHandler、ComponentScanBeanDefinitionParser。
直接从 parse() 开始看:

  1. 扫描包
    扫描包
  2. 过滤包含 @Component
    过滤包含 @Component-1过滤包含 @Component-2
  3. 填充 BeanDefinition
    填充 BeanDefinition-1
    填充 BeanDefinition-2
  4. 封装成 BeanDefinitionHolder,注册
    包装成 BeanDefinitionHolder
    注册
    注册与默认标签表示的 bean 注册相同。
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值