Java EE CDI实例 | 如何获取真实类

huangapple go评论101阅读模式
英文:

Java EE CDI Instance | How to get real class

问题

我正在尝试获取通过CDI注入的实例的真正类,但我只能获得一个类名的指定,该类名由接口名称、一系列数字和字符串“$Proxy$_$$_Weld$EnterpriseProxy$”组成。

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface TestProvider {
    String value();
}

public interface TestConnector {

}

@TestProvider("TestConnector1")
@Stateless
public class Test1 implements TestConnector {

}

@Default
@TestProvider("TestConnector2")
@Stateless
public class Test12 implements TestConnector {

}

@Stateless
public class TestFactory {

    @Inject
    @Any
    private Instance<TestConnector> testConnectors;

    public TestConnector getConnector(String name) {
        // ...
    }

    public Set<String> listAllTestConnectorNames() {
        try {
            Set<String> connectors = new HashSet<String>();

            this.testConnectors.forEach(con -> {
                System.out.println(con.getClass().getName());
                for (Annotation x : con.getClass().getAnnotations()) {
                    if (x instanceof TestProvider) {
                        String name = ((TestProvider) x).value();
                        System.out.println(name);
                        connectors.add(name);
                    }
                }
                this.testConnectors.destroy(con);
            });

            return connectors;
        } catch (Exception e) {
            // ...
        }
    }
}

函数listAllTestConnectorNames应该遍历所有确定的实例,并将注解TestProvider的值作为列表返回。我期望以下列表:

  • TestConnector1
  • TestConnector2

但我收到的实例是类型为de.test.con1.TestConnector $ 710153185 $ Proxy $ _ $$ _ Weld $ EnterpriseProxy $de.test.con2.TestConnector $ 219965632 $ Proxy $ _ $$ _ Weld $ EnterpriseProxy $

如何读取我正在寻找的值?

英文:

I am trying to get to the real classes of an instance that I injected via CDI.
I only get a designation as a class name, which is composed of the name of the interface, a sequence of numbers and the character string "$Proxy$_$$_Weld$EnterpriseProxy$".

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface TestProvider {
String value();
}
public interface TestConnector {
}
@TestProvider(&quot;TestConnector1&quot;)
@Stateless
public class Test1 implements TestConnector {
}
@Default
@TestProvider(&quot;TestConnector2&quot;)
@Stateless
public class Test12 implements TestConnector {
}
@Stateless
public class TestFactory {
@Inject
@Any
private Instance&lt;TestConnector&gt; testConnectors;
public TestConnector getConnector(String name) {
...
}
public Set&lt;String&gt; listAllTestConnectorNames(){
try {
Set&lt;String&gt; connectors = new HashSet&lt;String&gt;();
this.testConnectors.forEach(con -&gt; {
System.out.println(con.getClass().getName());
for(Annotation x : con.getClass().getAnnotations()) {
if(x instanceof TestProvider) {
String name = ((TestProvider) x).value();
System.out.println(name);
connectors.add(name);
}
}
this.testConnectors.destroy(con);
});
return connectors;
} catch(Exception e) {
...
}
}

The function listAllTestConnectorNames should go through all the determined instances and return the value of the annotation TestProvider as a list.
I would expect the following list.

  • TestConnector1
  • TestConnector2

But the instances that I received are of the type de.test.con1.TestConnector $ 710153185 $ Proxy $ _ $$ _ Weld $ EnterpriseProxy $ or
de.test.con2.TestConnector $ 219965632 $ Proxy $ _ $$ _ Weld $ EnterpriseProxy $

How can I read out the values I am looking for?

答案1

得分: 3

您的TestConnector实例正在被Weld代理,可能是因为它们处于正常范围内。这是正常且预期的。

因此,您的问题是:“给定一个(由Weld定义的)代理类,如何获取它所代理的'真实'类的名称?”

虽然没有一种被保证的方法可以起作用,但以下方法适用于Weld实现的CDI:

Weld的代理类在其上设置了SYNTHETIC标志,并且通常扩展了它们代理的类。我认为这不是一种保证,但在许多版本和多年的时间里都是如此。

因此,如果您执行类似于以下的操作:

Class<?> c = proxyClass;
while (c.isSynthetic()) {
  c = c.getSuperclass();
}
// 现在 c 是“真实”类
System.out.println(c.getName()); // 不应再是代理类的名称

...您应该可以获得预期结果。

英文:

Your TestConnector instances are being proxied by Weld, probably because they are in a normal scope. This is fine and expected.

Your question, therefore, is: "Given a (Weld-defined) proxy class, how do I get the name of the 'real' class it is proxying?"

There is not a way that is guaranteed to work, but this way will work with Weld implementations of CDI:

Weld's proxy classes have the SYNTHETIC flag set on them and in general extend the class they are proxying. I don't think this is guaranteed, but it has been true for many versions and many years now.

So if you do something like:

Class&lt;?&gt; c = proxyClass;
while (c.isSynthetic()) {
c = c.getSuperclass();
}
// Now c is the &quot;real&quot; class
System.out.println(c.getName()); // shouldn&#39;t be a proxy class name anymore

…you should be good.

huangapple
  • 本文由 发表于 2020年8月7日 18:19:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/63299807.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定