zoukankan      html  css  js  c++  java
  • Spring 中好用的泛型操作API

    随着泛型用的越来越多,获取泛型实际类型信息的需求也会出现,如果用原生API,需要很多步操作才能获取到泛型,比如:

    Java代码  收藏代码
    1. ParameterizedType parameterizedType =   
    2.     (ParameterizedType) ABService.class.getGenericInterfaces()[0];  
    3. Type genericType = parameterizedType.getActualTypeArguments()[1];  

    Spring提供的ResolvableType API,提供了更加简单易用的泛型操作支持,如:

    Java代码  收藏代码
    1. ResolvableType resolvableType1 = ResolvableType.forClass(ABService.class);  
    2. resolvableType1.as(Service.class).getGeneric(1).resolve()  

    对于获取更复杂的泛型操作ResolvableType更加简单。

    假设我们的API是:

    Java代码  收藏代码
    1. public interface Service<N, M> {  
    2. }  
    3.   
    4. @org.springframework.stereotype.Service  
    5. public class ABService implements Service<A, B> {  
    6. }  
    7.   
    8. @org.springframework.stereotype.Service  
    9. public class CDService implements Service<C, D> {  
    10. }  

    如上泛型类非常简单。 

    1、得到类型的泛型信息

    Java代码  收藏代码
    1. ResolvableType resolvableType1 = ResolvableType.forClass(ABService.class);  

    通过如上API,可以得到类型的ResolvableType,如果类型被Spring AOP进行了CGLIB代理,请使用ClassUtils.getUserClass(ABService.class)得到原始类型。

    可以通过如下得到泛型参数的第1个位置(从0开始)的类型信息

    Java代码  收藏代码
    1. resolvableType1.getInterfaces()[0].getGeneric(1).resolve()  

    因为我们泛型信息放在 Service<A, B> 上,所以需要resolvableType1.getInterfaces()[0]得到;

    通过getGeneric(泛型参数索引)得到某个位置的泛型;

    resolve()把实际泛型参数解析出来

    2、得到字段级别的泛型信息

    假设我们的字段如下:

    Java代码  收藏代码
    1. @Autowired  
    2.  private Service<A, B> abService;  
    3.  @Autowired  
    4.  private Service<C, D> cdService;  
    5.   
    6.  private List<List<String>> list;  
    7.   
    8.  private Map<String, Map<String, Integer>> map;  
    9.   
    10.  private List<String>[] array;  

    通过如下API可以得到字段级别的ResolvableType

    Java代码  收藏代码
    1. ResolvableType resolvableType2 =  
    2.                 ResolvableType.forField(ReflectionUtils.findField(GenricInjectTest.class, "cdService"));  

    然后通过如下API得到Service<C, D>的第0个位置上的泛型实参类型,即C

    Java代码  收藏代码
    1. resolvableType2.getGeneric(0).resolve()  

    比如 List<List<String>> list;是一种嵌套的泛型用例,我们可以通过如下操作获取String类型:

    Java代码  收藏代码
    1. ResolvableType resolvableType3 =  
    2.                 ResolvableType.forField(ReflectionUtils.findField(GenricInjectTest.class, "list"));  
    3. resolvableType3.getGeneric(0).getGeneric(0).resolve();  

    更简单的写法

    Java代码  收藏代码
    1. resolvableType3.getGeneric(0, 0).resolve(); //List<List<String>> 即String   

    比如Map<String, Map<String, Integer>> map;我们想得到Integer,可以使用:

    Java代码  收藏代码
    1. ResolvableType resolvableType4 =  
    2.                 ResolvableType.forField(ReflectionUtils.findField(GenricInjectTest.class, "map"));  
    3. resolvableType4.getGeneric(1).getGeneric(1).resolve();  

    更简单的写法  

    Java代码  收藏代码
    1. resolvableType4.getGeneric(1, 1).resolve()  

    3、得到方法返回值的泛型信息

    假设我们的方法如下:

    Java代码  收藏代码
    1. private HashMap<String, List<String>> method() {  
    2.     return null;  
    3. }  

    得到Map中的List中的String泛型实参:

    Java代码  收藏代码
    1. ResolvableType resolvableType5 =  
    2.                 ResolvableType.forMethodReturnType(ReflectionUtils.findMethod(GenricInjectTest.class, "method"));  
    3. resolvableType5.getGeneric(1, 0).resolve();  

    4、得到构造器参数的泛型信息

    假设我们的构造器如下:

    Java代码  收藏代码
    1. public Const(List<List<String>> list, Map<String, Map<String, Integer>> map) {  
    2. }  

    我们可以通过如下方式得到第1个参数( Map<String, Map<String, Integer>>)中的Integer:

    Java代码  收藏代码
    1. ResolvableType resolvableType6 =  
    2.                 ResolvableType.forConstructorParameter(ClassUtils.getConstructorIfAvailable(Const.class, List.class, Map.class), 1);  
    3. resolvableType6.getGeneric(1, 0).resolve();  

    5、得到数组组件类型的泛型信息

    如对于private List<String>[] array; 可以通过如下方式获取List的泛型实参String:

    Java代码  收藏代码
    1. ResolvableType resolvableType7 =  
    2.                 ResolvableType.forField(ReflectionUtils.findField(GenricInjectTest.class, "array"));  
    3. resolvableType7.isArray();//判断是否是数组  
    4. resolvableType7.getComponentType().getGeneric(0).resolve();  

    6、自定义泛型类型

    Java代码  收藏代码
    1. ResolvableType resolvableType8 = ResolvableType.forClassWithGenerics(List.class, String.class);  
    2.         ResolvableType resolvableType9 = ResolvableType.forArrayComponent(resolvableType8);  
    3. resolvableType9.getComponentType().getGeneric(0).resolve();  

    ResolvableType.forClassWithGenerics(List.class, String.class)相当于创建一个List<String>类型;

    ResolvableType.forArrayComponent(resolvableType8);:相当于创建一个List<String>[]数组;

    resolvableType9.getComponentType().getGeneric(0).resolve():得到相应的泛型信息;

    7、泛型等价比较:

    Java代码  收藏代码
    1. resolvableType7.isAssignableFrom(resolvableType9)  

    如下创建一个List<Integer>[]数组,与之前的List<String>[]数组比较,将返回false。

    Java代码  收藏代码
    1. ResolvableType resolvableType10 = ResolvableType.forClassWithGenerics(List.class, Integer.class);  
    2. ResolvableType resolvableType11= ResolvableType.forArrayComponent(resolvableType10);  
    3. resolvableType11.getComponentType().getGeneric(0).resolve();  
    4. resolvableType7.isAssignableFrom(resolvableType11);  

    从如上操作可以看出其泛型操作功能十分完善,尤其在嵌套的泛型信息获取上相当简洁。目前整个Spring4环境都使用这个API来操作泛型信息。

    如之前说的泛型注入:Spring4新特性——泛型限定式依赖注入,通过在依赖注入时使用如下类实现:

    GenericTypeAwareAutowireCandidateResolver

    QualifierAnnotationAutowireCandidateResolver

    ContextAnnotationAutowireCandidateResolver

    还有如Spring的核心BeanWrapperImpl,以及整个Spring/SpringWevMVC的泛型操作都是替换为这个API了:GenericCollectionTypeResolver和GenericTypeResolver都直接委托给ResolvableType这个API。

    参考博客:http://jinnianshilongnian.iteye.com/blog/1993608

  • 相关阅读:
    JDBC批处理数据
    JSP+Servlet 无数据库模拟登录过程
    idea常用插件
    如何破解IntelliJ IDEA2018教程
    java在线工具
    mysql快捷修改密码
    jdk1.8新特性
    java基础感觉白学了
    论JDK源码的重要性:一道面试题引发的无限思考
    数组算法经典实例
  • 原文地址:https://www.cnblogs.com/chenkeyu/p/9146859.html
Copyright © 2011-2022 走看看