`
jinnianshilongnian
  • 浏览: 21504281 次
  • 性别: Icon_minigender_1
博客专栏
5c8dac6a-21dc-3466-8abb-057664ab39c7
跟我学spring3
浏览量:2418715
D659df3e-4ad7-3b12-8b9a-1e94abd75ac3
Spring杂谈
浏览量:3008839
43989fe4-8b6b-3109-aaec-379d27dd4090
跟开涛学SpringMVC...
浏览量:5639514
1df97887-a9e1-3328-b6da-091f51f886a1
Servlet3.1规范翻...
浏览量:259936
4f347843-a078-36c1-977f-797c7fc123fc
springmvc杂谈
浏览量:1597348
22722232-95c1-34f2-b8e1-d059493d3d98
hibernate杂谈
浏览量:250226
45b32b6f-7468-3077-be40-00a5853c9a48
跟我学Shiro
浏览量:5858976
Group-logo
跟我学Nginx+Lua开...
浏览量:702014
5041f67a-12b2-30ba-814d-b55f466529d5
亿级流量网站架构核心技术
浏览量:785231
社区版块
存档分类
最新评论

Spring4新特性——更好的Java泛型操作API

阅读更多

Spring4新特性——泛型限定式依赖注入

Spring4新特性——核心容器的其他改进

Spring4新特性——Web开发的增强

Spring4新特性——集成Bean Validation 1.1(JSR-349)到SpringMVC 

Spring4新特性——Groovy Bean定义DSL

Spring4新特性——更好的Java泛型操作API 

Spring4新特性——JSR310日期API的支持

Spring4新特性——注解、脚本、任务、MVC等其他特性改进 

 

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

ParameterizedType parameterizedType = 
    (ParameterizedType) ABService.class.getGenericInterfaces()[0];
Type genericType = parameterizedType.getActualTypeArguments()[1];

 

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

ResolvableType resolvableType1 = ResolvableType.forClass(ABService.class);
resolvableType1.as(Service.class).getGeneric(1).resolve()

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

 

假设我们的API是:

public interface Service<N, M> {
}

@org.springframework.stereotype.Service
public class ABService implements Service<A, B> {
}

@org.springframework.stereotype.Service
public class CDService implements Service<C, D> {
}

如上泛型类非常简单。 

 

1、得到类型的泛型信息

ResolvableType resolvableType1 = ResolvableType.forClass(ABService.class);

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

 

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

resolvableType1.getInterfaces()[0].getGeneric(1).resolve()

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

 

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

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

 

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

假设我们的字段如下:

   @Autowired
    private Service<A, B> abService;
    @Autowired
    private Service<C, D> cdService;

    private List<List<String>> list;

    private Map<String, Map<String, Integer>> map;

    private List<String>[] array;

 

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

ResolvableType resolvableType2 =
                ResolvableType.forField(ReflectionUtils.findField(GenricInjectTest.class, "cdService"));

 

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

resolvableType2.getGeneric(0).resolve()

 

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

ResolvableType resolvableType3 =
                ResolvableType.forField(ReflectionUtils.findField(GenricInjectTest.class, "list"));
resolvableType3.getGeneric(0).getGeneric(0).resolve();

 

更简单的写法

resolvableType3.getGeneric(0, 0).resolve(); //List<List<String>> 即String 

 

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

ResolvableType resolvableType4 =
                ResolvableType.forField(ReflectionUtils.findField(GenricInjectTest.class, "map"));
resolvableType4.getGeneric(1).getGeneric(1).resolve();

更简单的写法  

resolvableType4.getGeneric(1, 1).resolve()

 

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

假设我们的方法如下:

private HashMap<String, List<String>> method() {
    return null;
}

 

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

ResolvableType resolvableType5 =
                ResolvableType.forMethodReturnType(ReflectionUtils.findMethod(GenricInjectTest.class, "method"));
resolvableType5.getGeneric(1, 0).resolve();

 

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

假设我们的构造器如下:

public Const(List<List<String>> list, Map<String, Map<String, Integer>> map) {
}

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

ResolvableType resolvableType6 =
                ResolvableType.forConstructorParameter(ClassUtils.getConstructorIfAvailable(Const.class, List.class, Map.class), 1);
resolvableType6.getGeneric(1, 0).resolve();

 

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

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

ResolvableType resolvableType7 =
                ResolvableType.forField(ReflectionUtils.findField(GenricInjectTest.class, "array"));
resolvableType7.isArray();//判断是否是数组
resolvableType7.getComponentType().getGeneric(0).resolve();

 

6、自定义泛型类型

ResolvableType resolvableType8 = ResolvableType.forClassWithGenerics(List.class, String.class);
        ResolvableType resolvableType9 = ResolvableType.forArrayComponent(resolvableType8);
resolvableType9.getComponentType().getGeneric(0).resolve();

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

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

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

 

7、泛型等价比较:

resolvableType7.isAssignableFrom(resolvableType9)

 

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

ResolvableType resolvableType10 = ResolvableType.forClassWithGenerics(List.class, Integer.class);
ResolvableType resolvableType11= ResolvableType.forArrayComponent(resolvableType10);
resolvableType11.getComponentType().getGeneric(0).resolve();
resolvableType7.isAssignableFrom(resolvableType11);

 

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

 

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

GenericTypeAwareAutowireCandidateResolver

QualifierAnnotationAutowireCandidateResolver

ContextAnnotationAutowireCandidateResolver

 

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

 

所以大家以后对泛型操作可以全部使用这个API了,非常好用。测试用例请参考GenricInjectTest.java

 

11
5
分享到:
评论
3 楼 SoberChina 2017-04-12  
有具体的实现场景吗?
2 楼 qq122343779 2014-06-18  
同上,study...
1 楼 andyny2006 2013-12-25  
study...

相关推荐

    Spring4新特性(6)更好的Java泛型操作APIJa

    在Spring4框架中,开发者们迎来了一项重要的更新——更优的Java泛型操作API。这一新特性极大地提升了代码的可读性和可维护性,同时也为开发者提供了更强大的工具来处理泛型类型。本文将深入探讨Spring4在这个领域所...

    SSH泛型代码实例

    SSH泛型代码实例是关于Java编程中的一种常见技术——Spring、Struts和Hibernate(SSH)框架结合使用泛型的应用示例。泛型是Java SE 5.0引入的一个重要特性,它允许在编译时检查类型安全,并且所有的强制转换都是自动...

    java爱好者的好帮手——java类库

    学习和熟练运用这些Java类库,不仅能够提升编程效率,还能帮助开发者更好地理解和应用Java的特性。对于初学者,可以通过阅读API文档、实践项目和参考书籍来逐步掌握这些知识。同时,不断更新的Java版本会引入新的...

    spring-framework-reference 3.0

    Spring 3.0 针对Java 5做了全面的升级,这意味着它充分利用了Java 5中的新特性,如泛型、枚举类型等。这些新特性不仅提高了代码的可读性和可维护性,还增加了编译时的安全检查。 ##### 5. Java 基于元数据的配置 ...

    Java学习材料(499篇文章)——Java学习材料(499篇文章)

    10. **泛型**: 泛型增强了代码的类型安全性,允许在编译时检查类型,并提供了更好的代码重用。 11. **注解(Annotation)**: 注解提供了一种向编译器或JVM提供元数据的方式,常用于配置框架(如Spring)或实现元编程...

    java知识精讲+500+面试题.zip

    15. **Java 8及以后的新特性**:如Lambda表达式、Stream API、Optional类等,这些新特性极大地提高了Java的编程效率。 以上只是Java知识体系的一小部分,实际的面试可能会涉及到更多细节,如JDK源码分析、性能调优...

    spring技术文档

    Spring 2.0提供了一系列更新的示例应用程序,帮助开发者更好地理解新特性的使用方法。 **2.9 文档改进** Spring 2.0的官方文档得到了大幅改进,提供了更加详尽的指南和教程,以帮助开发者快速上手。 #### 三、...

    java精华(水木清华站)

    14. **Java 8及以后的新特性**:Java 8引入了Lambda表达式、函数式接口、Stream API等新特性,提高了代码简洁性和效率;Java 11及更高版本也有新的改进和增强。 "Java精华(水木清华站)"可能涵盖以上部分或全部内容...

    java经典问题.rar

    Java编程语言自1995年发布以来,一直以其跨平台、面向对象和安全性等特点深受开发者喜爱。在Java的学习和实践中,经常会遇到一些经典问题,这些问题不仅有助于...通过深入学习和实践,可以更好地掌握Java编程的精髓。

    2021 Java学习路线,已助我成功拿到offer(csdn)————程序.pdf

    最后,为了更好地准备面试和提升学习效率,可以参考作者提到的免费分享的Java学习路线文档,涵盖相关知识点的题目和解答。通过系统的学习和实践,你将能更全面地掌握Java,增加自己在竞争激烈的就业市场中的优势。祝...

    spring's dist.jar

    在Spring 2.5版本中,dist.jar进一步强化了对Java 5特性的支持,如注解(Annotations)、泛型(Generics)等,显著提升了代码的可读性和可维护性。 dist.jar包含的主要模块有: 1. **IoC容器**:Spring的IoC容器是...

    良葛格Java JDK 5.0学习笔记

    在IO流方面,NIO(New IO)在Java 5.0中被引入,提供了一种基于通道(Channel)和缓冲区(Buffer)的I/O模型,相比于传统的流模型,NIO具有更好的非阻塞和选择器特性,适合处理大量并发连接。 最后,JDK 5.0对日期...

    jdk-8u152-windows-x64

    6. **改进的类型推断**:编译器可以更好地推断泛型的类型,减少了类型声明的需要。 7. **Nashorn JavaScript引擎**:JDK 8包含了Nashorn JavaScript引擎,可以直接在Java应用中执行JavaScript代码。 **安装与配置:...

    200道java程序员面试常问知识点

    4. Java集合框架:对List、Set、Map等集合的实现类及其特性有深入了解,包括它们的数据结构、排序和搜索机制。 5. 并发编程:理解线程的创建和运行机制、线程安全、同步机制(synchronized、lock)、死锁、线程池的...

    JAVA上百实例源码以及开源项目源代码

    Java局域网通信——飞鸽传书源代码 28个目标文件 内容索引:JAVA源码,媒体网络,飞鸽传书 Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java...

    关于j2ee的学习规划。关于学习的流程跟相应推荐的书籍

    此外,还应该了解Java反射机制,并熟悉Java 1.5之后引入的新特性,如泛型等。 #### 二、JAVA网络编程 在掌握了Java语言基础后,接下来可以进一步学习Java在网络编程方面的应用,这包括但不限于以下内容: - **...

    jdk-8u66-linux-x64源代码

    在Java中,包(package)是一种组织类和接口的方式,帮助避免命名冲突并提供更好的代码管理。 1. **javax**: 这个包通常包含Java扩展框架的一部分,其中包含了标准Java库没有提供的额外功能,如JavaBeans、Java...

    jackson-mapper-asl-1.9.12.jar

    另外,Jackson库本身也在不断更新和发展,新版本引入了更多优化和特性,例如支持JSON-P(JSR 353)和JSON-B(JSR 367),以及对Java 8新特性的支持。 综上所述,`jackson-mapper-asl-1.9.12.jar`是Java开发中处理...

    SCJP详细大纲 多线程

    根据提供的文件信息,我们可以将SCJP(Sun Certified Java Programmer)的大纲内容进行详细的解析与扩展。...以上内容是根据SCJP大纲整理的详细知识点概述,希望能够帮助学习者更好地理解和掌握Java的核心概念与技术。

Global site tag (gtag.js) - Google Analytics