`
tedeyang
  • 浏览: 328318 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

妙用注解和动态代理解决数据转换问题

阅读更多


直接转帖ajoo的大作

http://www.iteye.com/topic/190440

内容节选如下:

Java代码
  1. Map <String, String>  
Map

<String, String>


非常非常复杂深奥。

好,现在我们事先知道要从这个map 里读取一些数据点,比如:id , name , sex等等。

id ,我们知道读出来的是int;对name ,是string;对sex,应该对应一个叫Gender的enum类型。

这就涉及一个自动类型转换的问题。我们希望不用对每个数据点做手工类型转换。

另外一个需求,一些数据点是有缺省值的。比如name 我们可以缺省为空字符串。
这样,如果map 里面没有某个值,我们就看缺省值,如果有,就用这个缺省值,如果没有,就抛异常。

手工做的话,大概是这样:

Java代码 复制代码
  1. String id Value = map .get( "id " );   
  2. if  (id Value ==  null ) {   
  3.    throw  ...;   
  4. }   
  5. int  id  = Integer.parseInt(id Value);   
  6.   
  7. String name  = map .get( "name " );   
  8. if  (name  ==  null ) {   
  9.   name  =  "" ;   
  10. }   
  11.   
  12. String sexValue = map .get( "sex" );   
  13. if  (sexValue ==  null ) {   
  14.    throw  ...;   
  15. }   
  16. Gender sex = Gender.valueOf(sexValue);   
  17. ...  
String id

Value = map

.get("id

"); if (id

Value == null) {   throw ...; } int id

 = Integer.parseInt(id

Value);  String name

 = map

.get("name

"); if (name

 == null) {   name

 = ""; }  String sexValue = map

.get("sex"); if (sexValue == null) {   throw ...; } Gender sex = Gender.valueOf(sexValue); ... 



比较痛苦。于是做了一个动态代理

Java代码 复制代码
  1. public   final   class  PropertyConverter<T> {   
  2.    private   final  Class<T> targetType;   
  3.      
  4.    private  PropertyConverter(Class<T> targetType) {...}   
  5.   
  6.    public   static  <T> PropertyConverter<T> to(Class<T> targetType) {   
  7.      return   new  PropertyConverter<T>(targetType);   
  8.   }   
  9.   
  10.    public  T from( final  Map <String, String> map ) {   
  11.      return  Proxy.newProxyInstance(   
  12.        new  Class[]{targetType}, targetType.getClassLoader(),  new  InvocationHandler() {   
  13.          public  Object invoke(Object proxy, Method method, Object[] args) {   
  14.           String value = map .get(method.getName ());   
  15.            if  (value ==  null ) {   
  16.             Object defaultValue = method.getDefaultValue();   
  17.              if  (defaultValue ==  null ) {   
  18.                throw  ...;   
  19.             }   
  20.              return  defaultValue;   
  21.           }   
  22.            return  convert(value, method.getReturnType());   
  23.         }   
  24.     });   
  25.   }   
  26. }  
public final class PropertyConverter<T> {   private final Class<T> targetType;      private PropertyConverter(Class<T> targetType) {...}    public static <T> PropertyConverter<T> to(Class<T> targetType) {     return new PropertyConverter<T>(targetType);   }    public T from(final Map

<String, String> map

) {     return Proxy.newProxyInstance(       new Class[]{targetType}, targetType.getClassLoader(), new InvocationHandler() {         public Object invoke(Object proxy, Method method, Object[] args) {           String value = map

.get(method.getName

());           if (value == null) {             Object defaultValue = method.getDefaultValue();             if (defaultValue == null) {               throw ...;             }             return defaultValue;           }           return convert(value, method.getReturnType());         }     });   } } 



convert()函数是调用apache的ConvertUtilsBean做的,没什么说的。

那么,用法呢?

Java代码 复制代码
  1. @interface  Foo {   
  2.    int  id ();   
  3.   String name ()  default   "" ;   
  4.   Gender sex();   
  5. }   
  6.   
  7. Map <String, String> map  = ...;   
  8. Foo foo = PropertyConverter.to(Foo. class ).from(map );   
  9. foo.id ();   
  10. foo.name ();  
@interface Foo {   int id

();   String name

() default "";   Gender sex(); }  Map

<String, String> map

 = ...; Foo foo = PropertyConverter.to(Foo.class).from(map

); foo.id

(); foo.name

(); 



这里面,对annotation的用法比较特别。不过不这么做,java也不提供一个简单并且类型安全的指定缺省值的方法。当然,如果你凑巧不需要缺省值,那么也不用annotation,直接用interface就好。

 

我的补充:

动态代理(或者静态代理模式)在处理通用过程方面确实是非常常见的解决方案。
我们目前用到的spring的事务管理模块,buffalo,都是采用的动态代理技术。

做了这么久的开发,作为一个中级程序员,看到很繁琐累赘的代码四散在项目里时,我们就应该考虑设计模式了。
因为良好的设计,往往可以减少大量的代码量和工作时间,使项目结构清晰易读,容易重构升级,并减少bug!

不同于软件界面的改进,虽然老板看不见(/看不懂)产品内在的进化和我们冥思苦想的技术结晶,但它可以让我们活得更轻松,做得更好,更加游刃有余。
我一直自认是个”懒“人,也觉得每个程序员都应该变得更”懒“,凡是可以让我们更快开发,更快测试,更快发布的技术/方案/思想都应该迅速学习和接收,自己也要能开发、积累趁手的工具来加强效率。
据说IBM有个统计,不同水平程序员之间的开发效率差距最大可以达到恐怖的20倍!估计那都是日积月累之功,但如果个体不会思考,不想进步,那工作再久也是不能升华的。

谨以此同勉!

 

【2008-6 bbs】

 

后记:

后来我在项目应用了这个技巧,读取配置文件很方便,主要是有代码完成。缺点是如果增添配置文件的属性则需要增添接口的方法,这带来一点麻烦。

0
0
分享到:
评论

相关推荐

    注解和反射机制的学习笔记

    在Java编程语言中,注解(Annotation...在实际项目中,合理运用注解和反射可以解决许多复杂问题,提高代码的可读性和可维护性。通过深入学习和实践,开发者能够进一步挖掘Java的潜力,设计出更加高效和灵活的应用程序。

    java 动态代理模式 适配器模式

    在Java中,动态代理模式主要依赖于Java的反射API和InvocationHandler接口,而适配器模式则用于解决不同接口之间的兼容问题。 动态代理模式的核心在于能够在运行时动态创建一个实现指定接口的代理类,这个代理类可以...

    spring中注解的实现原理

    Spring使用BeanDefinitionReader来读取和解析注解,然后将注解信息转换为BeanDefinition对象。这个过程发生在ApplicationContext启动时。当Spring扫描指定的包路径时,它会查找带有特定注解的类,并根据注解的属性...

    java反射机制与动态代理

    ### Java反射机制与动态代理 ...动态代理则是反射机制的一种应用,它允许我们在运行时动态地创建接口的代理实现类,从而实现对现有类的扩展和增强。这些技术对于构建灵活和可扩展的应用程序非常重要。

    利用java反射、注解及泛型模拟ORM实现

    4. **执行SQL**:使用Java的JDBC API执行SQL,处理结果集,并将数据转换为Java对象,或将Java对象转换为数据库记录。 5. **泛型接口**:创建泛型的DAO接口,如`GenericDAO&lt;T&gt;`,其中T代表任何实现了ORM注解的实体类...

    JAVA设计模式--程序设计--反射--注解--泛型

    通过反射,我们可以动态地创建对象、调用方法、访问和修改私有属性,实现动态加载类,以及进行元数据分析等。反射的应用场景广泛,如插件系统、框架设计、单元测试等。 注解(Annotation)是Java中的元数据,它为...

    14、JavaSE:注解和反射.pdf

    Java注解(Annotation)是...通过结合使用内置注解和自定义注解,开发者可以定制化编译过程,实现诸如依赖注入、持久化、动态代理等高级功能。了解和熟练掌握注解的使用,对于提升Java编程效率和代码质量具有重要意义。

    java注解_反射_字节码_类加载机制.zip

    Java注解、反射、字节码和类加载机制是Java编程中的核心概念,它们在实际开发中扮演着重要角色。让我们深入探讨这些知识点。 **Java注解(Annotation)**: Java注解是一种元数据,它提供了在编译时或运行时处理代码的...

    SpringAOP注解特棒例子

    可以用来处理方法返回值,例如进行数据转换或处理。 5. `@AfterThrowing`:异常后通知,当目标方法抛出异常时执行。可以用来进行异常处理,如发送错误通知。 6. `@Around`:环绕通知,是最强大的通知类型,可以在...

    Spring注解详解

    在Spring JDBC中,数据访问异常会被转换成Spring的数据访问异常体系,从而使得异常处理更为统一和简洁。 **Spring事务管理** 事务管理是Spring框架中用于确保数据一致性和完整性的服务。Spring提供了对声明式事务和...

    Spring3MVC注解教程.ppt

    4、数据转换、格式化、校验 5、数据模型控制 6、视图及解析器 7、其它 目录: Spring MVC 3.0新特性 Spring MVC框架结构 Spring MVC框架结构 框架的实现者 目录 HTTP请求映射原理 Spring MVC进行映射的...

    spring的注解.docx

    这个注解通常用在业务逻辑层、数据访问层和视图层的类上。 2. **@Service**: @Service是@Component的一个特殊版本,主要用在服务层(Service Layer)。虽然功能上与@Component相同,但它的存在是为了增加代码的...

    data-transformation-spring-cloud-stream:使用Spring Cloud Stream进行数据转换

    Spring Cloud Stream是一个强大的框架,专为构建消息驱动的...了解如何配置和使用各种中间件,以及如何定制数据转换逻辑,对于提升Java开发者的技能树至关重要。同时,这也为构建实时、流式数据处理管道奠定了基础。

    Mybatis系列教程Mybatis注解开发共9页.pdf

    这个9页的教程很可能会涵盖这些基础和进阶的Mybatis注解用法,帮助读者理解如何在实际项目中有效利用Mybatis注解进行数据访问。学习这些内容有助于开发者更高效地进行数据库操作,减少代码冗余,提高代码质量。

    SpringMVC框架中传递JSON数据时前台报406错误解决办法

    在这个例子中,`@ResponseBody`注解告诉Spring MVC将方法返回的对象转换为JSON,`produces = "application/json"`则设置了Content-Type。 如果以上步骤都已完成,但仍遇到406错误,可能的原因包括但不限于:前端...

    java动态性.rar

    Java动态性是Java编程语言中的一个重要特性,它使得程序在运行时可以改变其结构,比如添加、删除或修改类和对象的行为。...理解和掌握这些知识点,对于提升Java开发者的技能和解决实际问题的能力至关重要。

    bytebuddy 字节码增强 创建注解

    本资源主要关注如何使用ByteBuddy来创建和处理注解,这对于理解和实现元数据驱动的设计模式非常有用。 首先,理解注解(Annotation)在Java中的作用至关重要。注解是一种元编程机制,它为代码提供了一些附加信息,...

    python 爬虫开发-爬取北、上、广租房子的信息demo源码+注解清晰.zip

    此外,爬虫还需要考虑反爬策略,如设置合适的延时以避免被服务器封IP,使用代理IP池增加爬取的隐蔽性,以及处理验证码和登录验证等问题。在项目中,可能会看到如何使用`time.sleep()`控制爬取速度,以及如何集成代理...

    Spring的BeanFactory的接口注解

    ### Spring的BeanFactory的接口注解 #### 一、引言 在Spring框架中,`BeanFactory`是工厂模式的一种实现,它负责管理容器中的Bean的生命周期与依赖注入。了解`BeanFactory`及其相关接口的功能对于掌握Spring的核心...

    Mybatis代理开发

    在Mybatis中,代理开发是其核心特性之一,它允许我们实现动态SQL和事务管理,极大地提高了开发效率。下面将详细介绍Mybatis的代理开发以及相关知识点。 1. **Mybatis代理机制**: Mybatis通过动态代理(JDK Proxy...

Global site tag (gtag.js) - Google Analytics