英文:
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("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) {
...
}
}
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<?> c = proxyClass;
while (c.isSynthetic()) {
c = c.getSuperclass();
}
// Now c is the "real" class
System.out.println(c.getName()); // shouldn't be a proxy class name anymore
…you should be good.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论