(spring-第9回【IoC基础篇】)BeanFactoryPostProcessor,实例化Bean之前的第二大利器

继承结构图如上。在加载XML,注册bean definition之后,在实例化bean definition之前,必要的时候要用到BeanFactoryPostProcessor。它负责把XML中有些占位符式的属性还原成真实值。意思是说,有时候,XML中<bean>的属性值不固定,会随着外界因素变化,这时候,在<bean>中配置占位符,而另外定义一个属性文件来控制<bean>的属性。比如下面是一个数据库连接的XML配置:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close"
p:driverClassName="${driverClassName}"
p:url="${url}"
p:username="${userName}"
p:password="${password}" />
下面定义了一个jdbc.properties:
dbName=sampledb
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/${dbName}
#userName=root
#password=1234
从jdbc.properties读取属性值,然后赋值给<bean> xml中的类似${password}的占位符。这时就要用到BeanFactoryPostProcessor的实现类。在这个例子中,我们可以使用PropertyPlaceHolderConfigurer。
一个例子:
首先,一共四个文件:
Car.java:最简单的bean类,源码如下:
public class Car {
private String name;
private String color;
private double price;
private Log log=LogFactory.getLog(Car.class);
public Car(){
//name="宝马";
log.info("调用了Car的构造函数,实例化了Car..");
}
public String getName() {
。。。
。。。
后面省略了getter和setter方法。
Main.java,简单的启动类,如下:
public class Main {
private static Log log=LogFactory.getLog(Main.class);
public static void main(String args[]){
ApplicationContext ctx = new ClassPathXmlApplicationContext("com/mesopotamia/test2/*.xml");
Car car = ctx.getBean("car",Car.class);
log.info(car.toString());
}
}
car.properties,car的属性文件:
name=奥迪A6
color=黄色
price=50.00
beans.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" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:property-placeholder
location="classpath:com/mesopotamia/test2/car.properties"
file-encoding="utf8"
/>
<bean id="utf8" class="java.lang.String">
<constructor-arg value="utf-8"></constructor-arg>
</bean>
<bean id="car" class="com.mesopotamia.test2.Car"
p:name="${name}"
p:color="${color}"
p:price="${price}"/>
</beans>
运行结果如下:
2015-11-22 22:08:59,155 INFO [main] (Car.java:15) - 调用了Car的构造函数,实例化了Car..
2015-11-22 22:08:59,167 INFO [main] (Main.java:15) - 名字:奥迪A6 颜色:黄色 价格:50.0
在beans.xml中,
使用了context规则和p规则。
<context:property-placeholder下面的两个属性:寻找属性文件,并设定相应的编码方式(默认是ISO-8559-1,加载中文会乱码,所以要转码)
配置转码属性后要单独写一个13-15行的编码格式的bean(这一点稍微有点淡腾)。
占位符就如17行那样:${...}。
这样配置后,spring会自动寻找classpath:com/mesopotamia/test2/car.properties下面的相应属性,并以utf-8的格式编码后,赋值给id为car的bean definition的对应属性。
默认情况下,spring会自动启动PropertyPlaceHolderConfigurer这个工厂后处理器。
我们并没有手动注册PropertyPlaceHolderConfigurer,那么spring是如何根据context:property-placeholder就去加载PropertyPlaceHolderConfigurer了?
答案:之前有讲过META-INF文件夹里面的spring-handlers和spring-schemas文件,spring-handlers可以根据命名空间找到具体的处理类,下面是context规则的spring-handlers文件:
http\://www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler http\://www.springframework.org/schema/jee=org.springframework.ejb.config.JeeNamespaceHandler
http \://www.springframework.org/schema/lang=org.springframework.scripting.config.LangNamespaceHandler
http \://www.springframework.org/schema/task=org.springframework.scheduling.config.TaskNamespaceHandler
第一行告诉我们,context规则的对应处理类是org.springframework.context.config.ContextNamespaceHandler,我们现在进入这个类:
public class ContextNamespaceHandler extends NamespaceHandlerSupport {
public void init() {
registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());
registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());
registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());
registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());
}
}
第四行一目了然,spring看到property-placeholder,就new了一个PropertyPlaceholderBeanDefinitionParser对象。而这个对象里面有个方法:
@Override
protected Class getBeanClass(Element element) {
return PropertyPlaceholderConfigurer.class;
}
这样就清楚了。实际上,<context:property-placeholder下面的属性就是PropertyPlaceholderConfigurer下面的属性,下面是几个重要的属性:
locations:一个属性文件的话,location就够了,而多个属性文件则是locations,它承袭自:
PropertiesLoaderSupport(PropertyPlaceholderConfigurer的父类的父类)。类型为:Properties[]。
fileEncoding:编码格式。它也是PropertiesLoaderSupport的属性。
order:如果配置文件定义了多个PropertyPlaceholderConfigurer,order负责规定执行顺序。这个属性继承自PropertyResourceConfigurer。
placeholderPrefix:像${...}为例,"${"是占位头符。也可以定义为其他占位头符。比如如果你写成&&{...}&&,那么placeholderPrefix需要定义为&&{。
placeholderSuffix:占位尾符。这两个属性属于PropertyPlaceholderConfigurer。
一般情况下,实例化一个Bean之前是没有对属性进行赋值的,即使实例化的时候也不会进行赋值,这是相当于new了一个对象罢了。但是在配置文件中定义了<bean>的属性值的话,在实例化之前,加载了XML并形成BeanDefinition后,就已经把属性值加载了,这并不是实例化的过程,更不是使用bean对象时定义属性值的过程。
立志不坚,终不济事。
------<宋>朱熹
(spring-第9回【IoC基础篇】)BeanFactoryPostProcessor,实例化Bean之前的第二大利器的更多相关文章
- (spring-第6回【IoC基础篇】)BeanDefinition——实例化Bean之前的第一大利器。
上节讲了Bean实例化的内部机制,这里再复述一遍: ResourceLoader从系统中加载XML配置信息,并由Resource来表示. BeanDefinitionReader从Resource中读 ...
- Spring+SpringMVC+MyBatis+easyUI整合基础篇(六)maven整合SSM
写在前面的话 承接前文<Spring+SpringMVC+MyBatis+easyUI整合基础篇(五)讲一下maven>,本篇所讲述的是如何使用maven与原ssm项目整合,使得一个普 ...
- Spring+SpringMVC+MyBatis+easyUI整合基础篇(八)mysql中文查询bug修复
写在前面的话 在测试搜索时出现的问题,mysql通过中文查询条件搜索不出数据,但是英文和数字可以搜索到记录,中文无返回记录.本文就是写一下发现问题的过程及解决方法.此bug在第一个项目中点这里还存在, ...
- Spring+SpringMVC+MyBatis+easyUI整合基础篇(十一)SVN服务器进阶
日常啰嗦 上一篇文章<Spring+SpringMVC+MyBatis+easyUI整合基础篇(十)SVN搭建>简单的讲了一下SVN服务器的搭建,并没有详细的介绍配置文件及一些复杂的功能, ...
- Spring+SpringMVC+MyBatis+easyUI整合基础篇(十二)阶段总结
不知不觉,已经到了基础篇的收尾阶段了,看着前面的十几篇文章,真的有点不敢相信,自己竟然真的坚持了下来,虽然过程中也有过懒散和焦虑,不过结果还是自己所希望的,克服了很多的问题,将自己的作品展现出来,也发 ...
- Spring+SpringMVC+MyBatis+easyUI整合基础篇
基础篇 Spring+SpringMVC+MyBatis+easyUI整合基础篇(一)项目简介 Spring+SpringMVC+MyBatis+easyUI整合基础篇(二)牛刀小试 Spring+S ...
- (spring-第2回【IoC基础篇】)Spring的Schema,基于XML的配置
要深入了解Spring机制,首先需要知道Spring是怎样在IoC容器中装配Bean的.而了解这一点的前提是,要搞清楚Spring基于Schema的Xml配置方案. 在深入了解之前,必须要先明白几个标 ...
- (spring-第5回【IoC基础篇】)spring容器从加载配置文件到实例化bean的内部工作机制
前面讲过,spring的生命周期为:实例化前奏-->实例化-->实例化后期-->初始化前期-->初始化-->初始化后期-->bean的具体调用-->销毁前-- ...
- (spring-第3回【IoC基础篇】)spring的依赖注入-属性、构造函数、工厂方法等的注入(基于XML)
Spring要把xml配置中bean的属性实例化为具体的bean,"依赖注入"是关卡.所谓的"依赖注入",就是把应用程序对bean的属性依赖都注入到spring ...
随机推荐
- 关于WorkFlow的使用以及例子
近期做项目,项目需要用到工作流方面的技术,我在这里与大家分享一个workFlow学习的地址,共大家学习. http://www.cnblogs.com/foundation/ 各文档的说明: F资料├ ...
- Junit4入门
eclipse自带junit包,可右键直接新建junit类 静态引入:import static org.junit.Assert.* assert.*是类,静态引入会引入assert里的所有静态方法 ...
- PHP程序员面试技巧之口试题分享
网络上流传很广的一部分php工程师面试题目,有些phper们认为这些很形式,天下面试题目一大把,不能考核一个人的真实水平,其实细细研究起来,无论怎样,能存在就表明其有存在的价值.下面小编整理了12条P ...
- hdu------(4300)Clairewd’s message(kmp)
Clairewd’s message Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Other ...
- WEB前端性能优化:HTML,CSS,JS和服务器端优化
对前端开发工程师来说,前端性能优化的重要性是不言而喻的,最为大家所知的是YSLOW的23条优化规则,在我的理解中,性能优化不纯粹是指用户访问网站的速度,也包括开发的效率,这里我总结下我理解中的WEB前 ...
- grease monkey setTimeout
在grease monkey中要使用如下方法进行setTimeout var f = function(){alert(1); setTimeout(f,100); } var inst=setTim ...
- 对石家庄铁道大学网站的UI分析
学校网站的首页面的色调用的比较好看,用深蓝色体现了严谨治学的风范.然后就是网站的首页有 1,学校概况:学校简介 现任领导 历任领导 校史沿革 2,组织机构: 机构设置 院系设置 管理机构 直属单位 其 ...
- tomcat项目发布 更改小猫图标 及自定义错误404界面
tomcat发布项目的时候遇到些小问题 不过解决了 问题1. 整个服务器的404自定义界面问题 解决方法: 在tomcat安装目录下conf中web.xml中修改配置文件 <error-page ...
- GUID vs INT Debate【转】
http://blogs.msdn.com/b/sqlserverfaq/archive/2010/05/27/guid-vs-int-debate.aspx I recently read a bl ...
- OLAP vs OLTP: what makes the difference
OLAP vs OLTP: what makes the difference OLPT and OLAP are complementingtechnologies. You can't live ...