velocity 之坑:不同枚举类(enum)有相同的静态(static)方法,无法访问第二个枚举类...

问题描述:

当用velocity,需要在同一个页面调用两个不同java枚举类的静态方法时,如果有两个枚举类的静态方法同名,则页面上的第二个静态方法调用始终是访问的第一个枚举类方法。


以下是国外朋友详细的问题陈述:

I am using Apache Velocity where I'm calling static Methods on Enums. Now I have two Enums which both have the same static Method-Name. When I call the static Method on the first Enum all works fine. When I call the Method on the second Enum, I get the result of the first Enum.


Example:

public enum A{

  VALUE_A1(1), VALUE_A2(2);

  private int id;

  private A(int id){

      this.id = id;

  }

  public static A getById(int id){

    for (A a : values()){

      if (a.id==id){

        return a;

      }

    }

    return null;

  }

}

public enum B{

  VALUE_B1(1), VALUE_B2(2);

  private int id;

  private B(int id){

      this.id = id;

  }

  public static B getById(int id){

      ...

  }

}

I initialized both in Velocity the same way:


VelocityContext context = new VelocityContext();

context.put("A", A.class);

context.put("B", B.class);


context.put("value1", 1);

context.put("value2", 2);

When I now call these Methods in my template, there are some issues. Calling the Method getById() on Enum A works fine. Calling it on Enum B gives me the value of enum A as a result.


$A.getById($value1)

$B.getById($value1)


results in 

VALUE_A1

VALUE_A1

and not in 

VALUE_A1

VALUE_B1

as expected

When I rename the Method in B and change the template properly, all works fine, but thats not what I want. Am I missing something? Or is it a bug in Apache Velocity?


解决方案:

context.put("A", A.values()[0]);

context.put("B", B.values()[0]);


深入分析:

velocity解析静态类时,会调用静态类的 staticClass.getClass()去缓存静态方法调用,staticClass.getClass()始终是java.lang.Class, 所以velocity内部缓存的所有静态类,只要静态方法签名相同,都默认走缓存获取第一个具有相同方法签名的类对象,调用该类对象的静态方法。

velocity 1.7 源码:

org.apache.velocity.util.ClassUtils.getMethod(String, Object[], Class[], Object, InternalContextAdapter, SimpleNode, boolean):line 189

/*

       * like ASTIdentifier, if we have cache information, and the Class of

       * Object o is the same as that in the cache, we are safe.

       */

      if (icd != null && (o != null && icd.contextData == o.getClass())) //此处o.getClass() == java.lang.Class

      {


        /*

         * get the method from the cache

         */

        method = (VelMethod) icd.thingy;

      } 


org.apache.velocity.util.ClassUtils.getMethod(String, Object[], Class[], Object, InternalContextAdapter, SimpleNode, boolean):line 208

 if ((method != null) && (o != null))

        {

          icd = new IntrospectionCacheData();

          icd.contextData = o.getClass(); //此处任何静态类(eg:context.put("A", A.class);)的A.class.getClass() 都相同

          icd.thingy = method;


          context.icachePut(mck, icd);

        }




转载于:https://my.oschina.net/fdhay/blog/633095

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值