【问题标题】:Checking if class is proxified with CDI 1.2检查类是否被 CDI 1.2 代理
【发布时间】:2014-10-23 18:32:31
【问题描述】:

在 CDI 1.2 中有一种方法可以检查类实例是否被代理?我需要这个,因为我需要获取原始类的名称,而不是代理名称。

@Inject Bean bean;

public void sysout() {
    // will print something like com.Bean$$Weld9239823
    System.out.println(bean.getClass()); 

    // I don't know how to check if the bean instance if a proxy or real class instance
}

使用 Weld 类我可以完成这项工作:

public void sysout() {
    // will print true because this is a proxy
    System.out.println(ProxyObject.class.isAssignableFrom(bean)); 

    // will print com.Bean
    System.out.println(((TargetInstanceProxy) bean).getTargetInstance());
}

在 CDI 1.1 中没有方法可以做到这一点。如果添加了关于此的方法,我会在 CDI 1.2 文档中搜索,但我什么也没找到。

所以...我错过了一些东西,CDI 1.2 有一种方法可以获取原始类名和实例吗?或者如果没有,有一个简单的在近特征中添加这个特征?

【问题讨论】:

  • 找出bean类的用例是什么?考虑到您正在注入 Bean bean,您已经知道它实现了 Bean
  • 你试过这个解决方案了吗? stackoverflow.com/a/7504552/2492784

标签: java cdi weld


【解决方案1】:

对于 WildFly 上的 Weld,请执行以下操作:

public boolean isProxy(Object obj) {
    try{
        return Class.forName("org.jboss.weld.bean.proxy.ProxyObject").isInstance(obj);
    } catch (Exception e) {
        log.error("Unable to check if object is proxy", e);
    }
    return false;
}

要检索实际对象而不是代理(我需要对其进行序列化),我这样做:

public Object getObject(Object obj) {
    Field f = null;
    boolean isAccessible = false;
    try {
        for(Field fi : Class.forName(handler).getDeclaredFields()) {
            if(fi.getName().equals(field)) {
                f = fi;
                isAccessible = f.isAccessible();
                f.setAccessible(true);
            }
        }
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
    if(f == null) {
        throw new RuntimeException(new NoSuchFieldException(String.format(
                "The required field '%s' not found in '%s'. " +
                        "May be the code is obsolete for running on this application server.",
                field, method)));
    } else {
        try{
            obj = f.get(getHandler(obj));
            for(Method m : Class.forName(instance).getMethods()) {
                if(m.getName().equals(value)) {
                    return m.invoke(obj);
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            f.setAccessible(isAccessible);
        }
        throw new NoSuchMethodError(String.format(
               "The required method '%s' not found in '%s'. " +
                       "May be the code is obsolete for running on this application server.",
                value, instance));
    }
}

请注意,这可能是最黑暗的魔法,性能非常差,并且在任何 WildFly 更新时都可能中断,如果它们更改其中字段的类和方法。

【讨论】:

    【解决方案2】:

    您可以在代理的 cdi bean 中创建一个方法,例如

    public String getClassName() {
        return this.getClass().getName();
    }
    

    这不是最好的解决方案,而是一种通过代理获取类名的简单实用的方法......这样做的缺点是该方法必须在每个实现上......

    【讨论】:

      【解决方案3】:

      这是一个可怕的 hack,但对于 Weld(可能还有其他实现),您可以检查类名是否包含“代理”:possibleProxy.getClass().getSimpleName().contains("Proxy")。我仅将它用于记录目的,以获得包装类名称的清理版本:

      /**
       * Get the actual simple name of the objects class that might be wrapped by
       * a proxy. A "simple" class name is not fully qualified (no package name).
       *
       * @param possibleProxy an object that might be a proxy to the actual
       * object.
       * @return the simple name of the actual object's class
       */
      public static String getActualSimpleClassName(final Object possibleProxy) {
          final String outerClassName = possibleProxy.getClass().getSimpleName();
          final String innerClassName;
          if (outerClassName.contains("Proxy")) {
              innerClassName = outerClassName.substring(0, outerClassName.indexOf('$'));
          } else {
              innerClassName = outerClassName;
          }
          return innerClassName;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-05-22
        • 1970-01-01
        • 1970-01-01
        • 2022-11-22
        • 2011-11-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多