全网疯传的Spring学习笔记【自定义类型转换器、BeanPostProcessor】,看完我也想写一个了!
【摘要】 六、自定义类型转换器 6.1、类型转换器 我们写在Spring配置文件中赋值的值都是String类型的,但是我们的实体类是Interger类型的值,按照语法来说,String类型的值是不可以直接赋值给Integer类型的,但是为什么能直接赋值呢? 因为Spring内部帮我们进行了自动的类型转换,Spring通过类型转换器将配置文件中字符串类型的数据,转换成了对象中成员变量对应类型...
六、自定义类型转换器
6.1、类型转换器
我们写在Spring配置文件中赋值的值都是String类型的,但是我们的实体类是Interger类型的值,按照语法来说,String类型的值是不可以直接赋值给Integer类型的,但是为什么能直接赋值呢?
因为Spring内部帮我们进行了自动的类型转换,Spring通过类型转换器将配置文件中字符串类型的数据,转换成了对象中成员变量对应类型的数据,从而完成注入。
6.2、自定义类型转换器
6.2.1、问题引入
@Data
@AllArgsConstructor
@NoArgsConstructor
public class People {
private String name;
private Date birthday;
}
<bean id="people" class="com.domain.People">
<property name="name" value="XiaoLin"/>
<property name="birthday" value="2021-2-6"/>
</bean>
我们运行代码之后发现报错了,说String类型的值不可以转化为Date类型的值,说明Spring内部没有这个转换器。
Caused by: java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'java.util.Date' for property 'birthday': no matching editors or conversion strategy found
at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:262)
at org.springframework.beans.AbstractNestablePropertyAccessor.convertIfNecessary(AbstractNestablePropertyAccessor.java:585)
... 39 more
Spring内部没有提供特定类型转换器时,而程序员在应用的过程中又需要使用,所以需要程序员自己定义类型转换器。
6.2.2、代码实现
自定义类型转换器我们分为两步实现:
- 实现
Converter<转换前的类型, 转换后的类型>
接口,并且重写里面的方法。 - 在配置文件中进行转换器的注册
public class MyConverter implements Converter<String, Date> {// 他有两个泛型,一个是转换前的类型,另一个是转换后的类型
/*
convert方法的作用是将String->Date
parm:source代表的是配置文件中需要转换的内容
return:把转换好的值作为返回值,Spring会自动为属性赋值
*/
@Override
public Date convert(String source) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date parse = null;
try {
parse = sdf.parse(source);
} catch (ParseException e) {
e.printStackTrace();
}
return parse;
}
}
<!-- 类型转换器的注册,告诉Spring我们所创建的MyConverter类是类型转换器类,
Spring提供了一个类ConversionServiceFactoryBean来完成类型转换器的注册-->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters" >
<set>
<!-- 注册类型转换器-->
<ref bean="myConvert"/>
</set>
</property>
</bean>
6.2.3、注意细节
- 创建
ConversionServiceFactoryBean
标签的id
必须为conversionService
,不然不生效。 - 其实Spring已经内置了日期类型的转换器,但是他只支持以
/
作为分隔符的字符串的格式:2021/2/6,不支持其他的格式,如果你的字符串格式已经是这种,就无需再写自定义类型转换器。
七、BeanPostProcessor
7.1、概述
BeanPostProcessor称为后置处理Bean,他的作用是对Spring工厂所创建的对象进行二次加工,他是AOP的底层实现,他本质上是一个接口。
7.2、BeanPostProcessor分析
他是一个接口,要实现他的两个方法:
Object postProcessBeforeInitialization(Object bean,String beanName)
:他的作用是在Spring创建完对象后,在进行初始化方法之前,- 通过参数获取到Spring创建好的对象,执行
postProcessBeforeInitialization
方法进行加工,最终通过返回值返回这个加工好的对象给Spring。 Object postProcessAfterInitialization(Object bean,Stirng beanName)
:Spring执行完对象的初始化操作之后,运行postProcessAfterInitialization
方法进行加工,通过参数获取Spring创建好的对象,最终通过返回值返回给Spring。
在日常的开发中,我们很少去处理Spring的初始化操作,所以没有必要区分前后,所以一般只需要实现其中一个方法即可,且BeanPostProcessor会对Spring工厂中的所有对象进行加工。
7.3、代码实现
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
private Integer id;
private String name;
}
public class MyBeanPoster implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
// 要进行类型判断,如果不是Student类型的话直接返回,不然会报类型转换错误,因为Spring会把工厂中的所有对象进行加工处理
if (bean instanceof Student){
Student student = (Student) bean;
student.setName("lisi");
}
return bean;
}
}
<bean id="student" class="com.beanpost.Student">
<property name="id" value="10"/>
<property name="name" value="zs"/>
</bean>
<!--注册后置Bean-->
<bean id="myBeanProcessor" class="com.beanpost.MyBeanPoster"/>
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)