BeanWrapper 两个顶级接口:1.PropertyEditorRegistry 2.PropertyAccessor 而BeanWrapperImpl 扩展了PropertyEditoryRegistrySupport类,Spring为这个类提供了默认的实现,defaultEditors存放的是默认的,customerEditors存放的是自定义的编辑器,并且基本通过这种方式实现注册(defaultEditors.put(char.class,new CharacterEditor(false));
那么我们该如何自定义属性编辑器呢, Spring提供了PropertyEditorSupport 类,我们只需要继承这个类,然后@override需要的方法即可:
先看下相关的一些方法:
public void setAsText(String text) throws java.lang.IllegalArgumentException 这个方法就是解析字符串,我们要做的逻辑都是在这
public void setValue(Object value) 数据解析好了,总得赋值吧,ok,这个就是赋值的方法,同时我们可以发现参数是Object类型的
Talk is cheap,show me the code:
public class Boss
{
private Car car;
private String name;}
public class Car
{
private String name;
private Integer price;}
省略get/set
public class MyPropertyConfiguration extends PropertyEditorSupport
{
@Override
public void setAsText(String text) throws IllegalArgumentException
{
String[] split = text.split(",");
Car car=new Car();
car.setName(split[0]);
car.setPrice(Integer.parseInt(split[1]));
setValue(car);
}
}
最后只需要注册即可:
注意我们这里的property car 的value 是字符串类型,不再需要ref 一个额外的bean了,当然这种自定义支持Spring xml配置的形式,至于Java Config的形式,则就已经没必要了
结果:
Boss [car=Car [name=joker's car, price=12333], name=null
------------------------------------------------------------------------------------------
核心类:PropertyPlaceholderConfigurer
相关方法介绍:
protected void convertProperties(Properties props) //是PropertyResourceConfigurer中的方法,默认中这个方法会遍历然后交给下个方法
protected void convertProperties(Properties props) {
Enumeration> propertyNames = props.propertyNames();
while (propertyNames.hasMoreElements()) {
String propertyName = (String) propertyNames.nextElement();
String propertyValue = props.getProperty(propertyName);
String convertedValue = convertProperty(propertyName, propertyValue);
if (!ObjectUtils.nullSafeEquals(propertyValue, convertedValue)) {
props.setProperty(propertyName, convertedValue);
}
}
}
protected String convertProperty(String propertyName, String propertyValue) {
return convertPropertyValue(propertyValue);
} 这个方法又将任务给了下个方法 ,同时传入了名字,我们可以在这里进行具体的措施
protected String convertPropertyValue(String originalValue) {
return originalValue;
} 默认是什么都不处理的,不过我们也能发现,大牛们都喜欢将方法拆分
Talk is cheap,show me the code
简单修改下Car类:
@Value("${username}")
private String name;
private Integer price;}
public class MyPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer
{
@Override
protected String convertProperty(String propertyName, String propertyValue)
{
if(propertyName.equals("username"))
{
return propertyValue+"joker--lala";
}else
{
return convertPropertyValue(propertyName);
}
}
}
我们只需要复写有name和value的即可,因为我们要的只是某个key对应的value
@Configuration
public class PropertyConfiguration
{
@Bean
public MyPropertyPlaceholderConfigurer myPropertyPlaceholderConfigurer() throws IOException
{
MyPropertyPlaceholderConfigurer myPropertyPlaceholderConfigurer=new MyPropertyPlaceholderConfigurer();
myPropertyPlaceholderConfigurer.setLocations(new PathMatchingResourcePatternResolver().getResources("classpath:*.properties"));
return myPropertyPlaceholderConfigurer;
}
@Bean
public Car car()
{
return new Car();
}
}
注入然后调用即可,
public class TestClass2
{
public static void main(String[] args)
{
ApplicationContext context=new AnnotationConfigApplicationContext(PropertyConfiguration.class);
Car bean = context.getBean(Car.class);
System.out.println(bean);
}
}
结果如下:Car [name=clownjoker--lala, price=null]
Summary:
自定义属性的核心类:PorpertyEditorSuppor 和CustomEditorConfigurer
前者通过复写setAsText() 实现自己需要的bean属性的配置(非外部),后者则将其注册到map中,从而实现相关配置
自定义外部属性的核心类:PropertyPlaceholderConfigurer
通过复写PropertyResourceConfigurer 中的convertProperty(Stirng name,String value) 然后将其注册为bean即可