Spring预定义了很多容器后处理器,这里来看如下两个:
CustomEditorConfigurer 用来注册自定义的属性编辑器。
PropertyPlaceholderConfigurer 用来读取属性文件,同时内置了常用的属性编辑器。
实际练习:
通过容器后处理器,装配birthday、sex的转换和装配。
info.properties
username=tom
sex=true
Spring.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--ver1-->
<!--最开始的方法:springBean中注入address-->
<!--<bean id="address" class="ioc24.Address">
<property name="city" value="nanjing"/>
<property name="province" value="jiangsu"/>
</bean>
<bean id="springBean" class="ioc24.SpringBean">
<property name="address" ref="address"/>
</bean>-->
<!--BeanFactoryPostProcessor-->
<bean id="springBean" class="ioc24.SpringBean">
<property name="address" value="[临沂-山东]"/>
<property name="birthday" value="1990-12-26"/>
<property name="username" value="${username}"/>
<property name="sex" value="${sex}"/>
</bean>
<!--ver2-->
<!--将SpringBeanFacotoryPostProcessor添加到IoC容器中-->
<!--<bean class="ioc24.SpringBeanFacotoryPostProcessor">
<property name="cunstomEditors">
<map>
<entry key="ioc24.Address" value="ioc24.editor.AddressEditor"/>
<entry key="java.util.Date" value="ioc24.editor.DateEditor"/>
<entry key="java.lang.String" value="ioc24.editor.StringEditor"/>
<entry key="java.lang.Boolean" value="ioc24.editor.BooleanEditor"/>
</map>
</property>
</bean>-->
<!--ver3-->
<!--使用spring提供的CustomEditorConfigurer-->
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<!--注册属性编辑器-->
<property name="customEditors">
<map>
<entry key="ioc24.Address" value="ioc24.editor.AddressEditor"/>
<entry key="java.util.Date" value="ioc24.editor.DateEditor"/>
<!--这两个属性编辑器是我们自定义的,交给-->
<!--<entry key="java.lang.String" value="ioc24.editor.StringEditor"/>
<entry key="java.lang.Boolean" value="ioc24.editor.BooleanEditor"/>-->
</map>
</property>
</bean>
<!--使用spring提供的PropertyPlaceholderConfigurer-->
<!--内置了String Boolean等常用属性编辑器,字符串匹配、格式查找等内部都有实现-->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<!--该配置后,会自动读取属性文件-->
<property name="location" value="classpath:ioc24/info.properties"/>
</bean>
</beans>
package ioc24;
public class Address {
private String city;
private String province;
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
@Override
public String toString() {
return "Address{" +
"city='" + city + '\'' +
", province='" + province + '\'' +
'}';
}
}
package ioc24;
import java.util.Date;
public class SpringBean {
{
System.out.println("代码块");
}
private Address address;
private Date birthday;
private String username;
private Boolean sex;
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Boolean getSex() {
return sex;
}
public void setSex(Boolean sex) {
this.sex = sex;
}
@Override
public String toString() {
return "SpringBean{" +
"address=" + address +
", birthday=" + birthday +
", username='" + username + '\'' +
", sex=" + sex +
'}';
}
}
package ioc24.editor;
import ioc24.Address;
import java.beans.PropertyEditor;
import java.beans.PropertyEditorSupport;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/*
* 定义的属性编辑器
*/
//父类中方法较多,这里只需要重写getAsText setAsText
public class AddressEditor extends PropertyEditorSupport {
//用来将Address转换为String
@Override
public String getAsText() {
return super.getAsText();
}
//将String转换为Address
@Override
public void setAsText(String text) throws IllegalArgumentException {
Pattern pattern = Pattern.compile("\\[(.*)-(.*)\\]");
Matcher matcher = pattern.matcher(text);
if (matcher.matches()){
String city = matcher.group(1);
String provience = matcher.group(2);
Address address = new Address();
address.setCity(city);
address.setProvince(provience);
//调用setValue设置值
//说白了就是把修改属性之后的对象,交给容器
setValue(address);
}
}
}
package ioc24.editor;
import ioc24.Util.PropertiesUtils;
import java.beans.PropertyEditorSupport;
public class BooleanEditor extends PropertyEditorSupport {
@Override
public String getAsText() {
return super.getAsText();
}
@Override
public void setAsText(String text) throws IllegalArgumentException {
if(PropertiesUtils.matcher(text)){
String key = PropertiesUtils.getKey(text);
PropertiesUtils.load(StringEditor.class.getClassLoader().getResourceAsStream("ioc24/info.properties"));
//将字符串编程boolean
boolean b = Boolean.parseBoolean(PropertiesUtils.get(key).toString());
setValue(b);
}
}
}
package ioc24.editor;
import java.beans.PropertyEditorSupport;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateEditor extends PropertyEditorSupport {
//把日期对象变为文本
@Override
public String getAsText() {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
//把日期对象换成字符串
return simpleDateFormat.format((Date)getValue());
}
//将文本变为日期对象
@Override
public void setAsText(String text) throws IllegalArgumentException {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
try {
//得到日期对象
Date parse = simpleDateFormat.parse(text);
setValue(parse);
} catch (ParseException e) {
e.printStackTrace();
}
}
}
package ioc24.editor;
import ioc24.Util.PropertiesUtils;
import java.beans.PropertyEditorSupport;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class StringEditor extends PropertyEditorSupport {
@Override
public String getAsText() {
return super.getAsText();
}
//将spring.xml中的${username}变为属性文件中真正的值
@Override
public void setAsText(String text) throws IllegalArgumentException {
if (PropertiesUtils.matcher(text)){
String key = PropertiesUtils.getKey(text);
PropertiesUtils.load(StringEditor.class.getClassLoader().getResourceAsStream("ioc24/info.properties"));
String value = PropertiesUtils.get(key).toString();
setValue(value);
}
}
}
package ioc24.Util;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/*
* 读取properties文件的工具类
*/
public class PropertiesUtils {
private static Properties properties;
//读取属性文件
public static void load(InputStream inputStream) {
if (properties == null){
properties = new Properties();
}
try {
properties.load(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
//获取属性值
public static Object get(String key){
if (properties.containsKey(key)){
return properties.get(key);
}else {
throw new RuntimeException("在properties文件中找不到值,key:"+key);
}
}
//判断是否符合格式
public static boolean matcher(String string){
Pattern pattern = Pattern.compile("\\$\\{(.*)\\}");
Matcher matcher = pattern.matcher(string);
return matcher.matches();
}
//处理字符串
public static String getKey(String string){
Pattern pattern = Pattern.compile("\\$\\{(.*)\\}");
Matcher matcher = pattern.matcher(string);
if(matcher.matches()){
return matcher.group(1);
}else {
throw new RuntimeException("格式不正确,string:"+string);
}
}
}
package ioc24;
import ioc24.editor.AddressEditor;
import ioc24.editor.DateEditor;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import java.beans.PropertyEditor;
import java.util.Date;
import java.util.Map;
import java.util.Map.Entry;
/**
*定义容器后处理器
* 作用:通过注册属性编辑器,完成属性的转换和装配
*
*/
public class SpringBeanFacotoryPostProcessor implements BeanFactoryPostProcessor {
//cunstomEditors中存放的属性编辑器是ioc容器根据spring.xml自动注入的
private Map<Class,Class<? extends PropertyEditor>> cunstomEditors;
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("SpringBeanFacotoryPostProcessor.postProcessBeanFactory");
//向容器中注册属性编辑器
//第1个参数:要转换的属性类型 第2个参数:要使用的属性编辑器类型
//该属性编辑器在装配的时候,如果遇到Address类型的数据要装配,那就把value值经过AddressEditor进行转换,将String转换成Address类型,完成装配
/*beanFactory.registerCustomEditor(Address.class, AddressEditor.class);
beanFactory.registerCustomEditor(Date.class, DateEditor.class);*/
//上边每注册一个容器后处理器都要一个那一行代码,麻烦
//这里优化
//cunstomEditors.entrySet() 遍历键值对(Entry<key,value>)
for (Entry<Class,Class<? extends PropertyEditor>> entry : cunstomEditors.entrySet()){
beanFactory.registerCustomEditor(entry.getKey(),entry.getValue());
}
}
public Map<Class, Class<? extends PropertyEditor>> getCunstomEditors() {
return cunstomEditors;
}
public void setCunstomEditors(Map<Class, Class<? extends PropertyEditor>> cunstomEditors) {
this.cunstomEditors = cunstomEditors;
}
}
package ioc24;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String [] args){
ApplicationContext ac = new ClassPathXmlApplicationContext("ioc24/spring.xml");
System.out.println(ac.getBean("springBean"));
}
}