从源代码分析Spring处理property-placeholder原理

一、如何在Spring中将属性文件配置内容加载到环境中

1.1、在Spring的XML配置文件中配置<context:property-placeholder/>,由于<context:property-placeholder/>命名空间为

http://www.springframework.org/schema/context,通过命名空间名与处理程序的映射关系(Sping中配置的关系在sping.handlers文件中),

找到处理器http\://www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler

1.2、在ContextNamespaceHandler中的init()函数中注册了parser解析器this.registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());

1.3、调用PropertyPlaceholderBeanDefinitionParser.parse()函数开始解析XML中配置的属性

1.4、在PropertyPlaceholderBeanDefinitionParser.parse()函数中调用了AbstractSingleBeanDefinitionParser.parseInternal()函数构建

构建内部BeanDefinition,最后调用了AbstractPropertyLoadingBeanDefinitionParser.doParse()函数解析property-placeholder自定义的属性

1.5、最后将构建好的BeanDefinition注册到BeanDefinitionRegistry注册中心中供Spring上下文使用


二、如何使用加载到环境中的配置

2.1、Spring通过BeanFactoryProcessor进行扩展,Spring提供了PropertyPlaceholderConfigurer(其实现了BeanFactoryPostProcessor)

在Bean创建前将占位符使用配置文件中的配置值替换

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" 
        init-method="init" destroy-method="close">
    <property name="url" value="${jdbc.url}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>

</bean>

或者

@Value("${spring_only}")

private String springOnly;

2.2、通过两种方式注入

Bean方式:

单个配置文件

<bean id="propertyConfigurer"class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
   <property name="location">
     <value>conf/sqlmap/jdbc.properties</value>
   </property>
    <property name="fileEncoding">
      <value>UTF-8</value>
    </property>
</bean>
多个配置文件
<bean id="propertyConfigurer"class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">  
    <property name="locations">
        <list>
            <value>/WEB-INF/mail.properties</value>  
            <value>classpath: conf/sqlmap/jdbc.properties</value>//注意这两种value值的写法
     </list>
    </property>

</bean>

标签方式:

<context:property-placeholder location="classpath*:/WEB-INF/mail.properties" />

今天一个问题困扰了我一下午,因此必须记录下来

PropertyPlaceholderConfigurer类中的location、locations、localProperties分别为 Resource、Resource[]、Properties[]类型,

而XML中指定属性值时却是字符串类型,一直都不知道Spring在什么时候、通过哪种机制处理转换的(将字符串转换成Resource、Resource[]、Properties[])

研究了很久发现Spring提供了一些系统的属性编辑器(超类为PropertyEditorSupport),Spring在解析和赋值property时,会调用对应的编辑器处理

,且Spring会默认依据property的类型找对应的编辑器。比如Resource有对应的编辑器ResourceEditor,会将字符串值转换处理为Resource、Resource[]。

若想要改变默认的PropertyEditor,可以添加自定义的来覆盖它。在添加时可以使用一个自动检测的机制:也就是需要遵照一定的规则

具体的规则是:PropertyEditor类和标准的 JavaBeans在同一个包下,并且他们PropertyEditor的类名是JavaBeans的类名加上“Editor”,比如:

[java]  view plain  copy
  1. public class ExoticTypeEditor extends PropertyEditorSupport {  
  2.     public void setAsText(String text) {  
  3.         setValue(new ExoticType(text.toUpperCase()));  
  4.     }  
  5. }  

可以看到这个PropertyEditor就是遵照了以上的命名规则,并且和ExoticType放在同一个包中,所以无需额外的配置就可以得到下面的输出:

ANAMEFOREXOTICTYPE


那么若没有符合以上规则的话,怎么办呢?可以通过org.springframework.beans.factory.config.CustomEditorConfigurer这个Bean来注册

为这个Bean配置customEditors属性,该属性是一个Map,将我们需要注册的PropertyEditors都注入到这个Map里就可以了:

[html]  view plain  copy
  1. <bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">  
  2.     <property name="customEditors">  
  3.         <map>  
  4.             <entry key="document.six.test.ExoticType" value="document.six.test.ExoticType2Editor" />  
  5.         </map>  
  6.     </property>  
  7. </bean>  

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!--<context:component-scan base-package="com.tjise.bean"/>--> <!--数据库连接信息的属性文件 --> <context:property-placeholder location="classpath:jdbc-config.properties"/> <!-- 配置Druid数据源的Bean --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <!-- 配置SessionFactory的Bean --> <bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 注入数据源 --> <property name="dataSource" ref="dataSource"/> <!-- 指定MyBatis配置文件的位置 --> <property name="configLocation" value="classpath:mybatis.xml"/> <!-- 给实体类起别名 --> <property name="typeAliasesPackage" value="com.tjise.entity"/> </bean> <!-- 配置mapper接口的扫描器,将Mapper接口的实现类自动注入到IoC容器中 实现类Bean的名称默认为接口类名的首字母小写 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <!-- basePackage属性指定自动扫描mapper接口所在的包 --> <property name="basePackage" value="com.tjise.mapper"/> </bean> </beans>
最新发布
03-23
上述代码是一个基于Spring框架的XML配置文件,主要用于配置数据库连接、MyBatis以及相关的组件扫描功能。以下是对其内容的具体解析: ### 1. 基本结构说明 ```xml <?xml version="1.0" encoding="UTF-8"?> ``` 这是标准的XML声明头,表明这是一个版本为1.0并采用UTF-8编码的XML文档。 ```xml <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="...省略..."> ``` `<beans>`标签用于定义Spring容器的基本元素集合,并通过命名空间(如`xmlns:context`)引入额外的功能模块。`xsi:schemaLocation`指定了对应的XSD文件路径,以验证XML的有效性。 --- ### 2. 数据库属性 #### `<context:property-placeholder>` ```xml <context:property-placeholder location="classpath:jdbc-config.properties"/> ``` 该标签会从指定位置读取外部化的配置文件,在这里是从类路径下的`jdbc-config.properties`文件中获取键值对形式的数据库相关信息(例如驱动程序、URL等)。这有助于解耦硬编码和配置项之间的绑定关系。 --- ### 3. 配置Druid数据源 #### `<bean id="dataSource">` ```xml <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> ``` 这个部分创建了一个名为`dataSource`的数据源Bean实例,使用的是阿里巴巴开源的高性能数据库连接池工具——**Druid**。各个参数均来源于之前提到过的`jdbc-config.properties`配置文件中的占位符变量`${}`。 --- ### 4. MyBatis SqlSessionFactory Bean配置 #### `<bean id="sessionFactory">` ```xml <bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="configLocation" value="classpath:mybatis.xml"/> <property name="typeAliasesPackage" value="com.tjise.entity"/> </bean> ``` 此片段负责初始化MyBatis的核心工厂对象`SqlSessionFactory`。其中关键点包括: - **dataSource**: 引用了前面已定义好的`dataSource` Bean。 - **configLocation**: 指向了位于资源目录下具体的MyBatis主配置文件(`mybatis.xml`)。 - **typeAliasesPackage**: 扫描给定包内所有符合条件的类,并为之分配简短别名供SQL映射文件引用。 --- ### 5. Mapper接口扫描注册 #### `<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">` ```xml <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.tjise.mapper"/> </bean> ``` 为了方便操作DAO层持久化逻辑,通常会借助代理模式自动生成Mapper接口对应实现类并将它们注入IOC容器之中。上述设置即为此目的服务,只需告知需要搜索的目标基础包即可完成自动化处理过程。(这里的示例设成了`com.tjise.mapper`) --- 以上就是整个XML配置的主要组成部分及其作用概述! --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值