如何使用注释 @MyFormat("%td.%<tm.%<tY") 格式化 getBirthday()

How do I format getBirthday() with an annotation @MyFormat("%td.%<tm.%<tY")

如何生成一个 class,它接受一个 Person 实例并且 return 将生日作为字符串而不是用 @MyFormat 注释的值格式化的日期,而不编写该子class 手动?

目的是将生成的实例用于HTML页面生成

class Person {

    @MyFormat("%td.%<tm.%<tY")
    public Date getBirthday() { return birthday; }
}

// Usage somewhere in the code

...
List<Person> people = people.parallelStream()
    .map(p -> MyFormatInterceptor.wrap(p))
    .collect(toCollection(ArrayList::new));


System.out.println(people.iterator().next().getBirtday()) // 31.Mai.2015

我有这个(见下文)。

return 类型从 Date 更改为 String 无关紧要,因为调用是通过计算表达式 "person.birthday".

的反射进行的
new ByteBuddy()
   .subclass(person.getClass())
   .method(isAnnotatedWith(MyFormat.class))
   .intercept(MethodDelegation.to(MyFormatInterceptor.class))
   .make()
   .load(person.getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
   .getLoaded();

class MyFormatInterceptor {

    @RuntimeType 
    public static Object format(@Origin Method m, @SuperCall Callable<?> zuper) {

        MyFormat formatAnnotation = m.getAnnotation(MyFormat.class);

        return String.format(formatAnnotation.value(), zuper.call());
    }
}

因此新的 class 将具有相同的方法名称 "String getBirthday()" 但字符串作为 return 值。

我不完全确定我是否理解您要完成的任务。以下代码正在创建您不使用的 Person 的子类:

new ByteBuddy()
  .subclass(person.getClass())
  .method(isAnnotatedWith(MyFormat.class))
  .intercept(MethodDelegation.to(MyFormatInterceptor.class))
  .make()
  .load(person.getClass().getClassLoader(),                  
        ClassLoadingStrategy.Default.WRAPPER)
  .getLoaded();

当您在运行时使用这个生成的子类时,调用 getBirthday 方法会导致 ClassCastException,因为 String 值无法转换为 Date。 Byte Buddy 不会更改 return 类型,即使在通过反射调用方法时也是如此。