全网疯传的Spring学习笔记【自定义类型转换器、BeanPostProcessor】,看完我也想写一个了!

举报
XiaoLin_Java 发表于 2022/01/31 17:32:50 2022/01/31
【摘要】 六、自定义类型转换器 6.1、类型转换器    我们写在Spring配置文件中赋值的值都是String类型的,但是我们的实体类是Interger类型的值,按照语法来说,String类型的值是不可以直接赋值给Integer类型的,但是为什么能直接赋值呢?   因为Spring内部帮我们进行了自动的类型转换,Spring通过类型转换器将配置文件中字符串类型的数据,转换成了对象中成员变量对应类型...

六、自定义类型转换器

6.1、类型转换器

    我们写在Spring配置文件中赋值的值都是String类型的,但是我们的实体类是Interger类型的值,按照语法来说,String类型的值是不可以直接赋值给Integer类型的,但是为什么能直接赋值呢?

   因为Spring内部帮我们进行了自动的类型转换,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、代码实现

  自定义类型转换器我们分为两步实现:

  1. 实现Converter<转换前的类型, 转换后的类型>接口,并且重写里面的方法。
  2. 在配置文件中进行转换器的注册
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、注意细节

  1. 创建ConversionServiceFactoryBean标签的id必须为conversionService,不然不生效。
  2. 其实Spring已经内置了日期类型的转换器,但是他只支持以/作为分隔符的字符串的格式:2021/2/6,不支持其他的格式,如果你的字符串格式已经是这种,就无需再写自定义类型转换器。

七、BeanPostProcessor

7.1、概述

    BeanPostProcessor称为后置处理Bean,他的作用是对Spring工厂所创建的对象进行二次加工,他是AOP的底层实现,他本质上是一个接口。

7.2、BeanPostProcessor分析

    他是一个接口,要实现他的两个方法:

  1. Object postProcessBeforeInitialization(Object bean,String beanName):他的作用是在Spring创建完对象后,在进行初始化方法之前,
  2. 通过参数获取到Spring创建好的对象,执行postProcessBeforeInitialization方法进行加工,最终通过返回值返回这个加工好的对象给Spring。
  3. Object postProcessAfterInitialization(Object bean,Stirng beanName):Spring执行完对象的初始化操作之后,运行postProcessAfterInitialization方法进行加工,通过参数获取Spring创建好的对象,最终通过返回值返回给Spring。

    在日常的开发中,我们很少去处理Spring的初始化操作,所以没有必要区分前后,所以一般只需要实现其中一个方法即可,且BeanPostProcessor会对Spring工厂中的所有对象进行加工。

Spring-BeanPostProcessor

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

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。