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

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

Java EE CDI Instance | How to get real class

问题

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

  1. @Qualifier
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Target(ElementType.TYPE)
  4. public @interface TestProvider {
  5. String value();
  6. }
  7. public interface TestConnector {
  8. }
  9. @TestProvider("TestConnector1")
  10. @Stateless
  11. public class Test1 implements TestConnector {
  12. }
  13. @Default
  14. @TestProvider("TestConnector2")
  15. @Stateless
  16. public class Test12 implements TestConnector {
  17. }
  18. @Stateless
  19. public class TestFactory {
  20. @Inject
  21. @Any
  22. private Instance<TestConnector> testConnectors;
  23. public TestConnector getConnector(String name) {
  24. // ...
  25. }
  26. public Set<String> listAllTestConnectorNames() {
  27. try {
  28. Set<String> connectors = new HashSet<String>();
  29. this.testConnectors.forEach(con -> {
  30. System.out.println(con.getClass().getName());
  31. for (Annotation x : con.getClass().getAnnotations()) {
  32. if (x instanceof TestProvider) {
  33. String name = ((TestProvider) x).value();
  34. System.out.println(name);
  35. connectors.add(name);
  36. }
  37. }
  38. this.testConnectors.destroy(con);
  39. });
  40. return connectors;
  41. } catch (Exception e) {
  42. // ...
  43. }
  44. }
  45. }

函数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$".

  1. @Qualifier
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Target(ElementType.TYPE)
  4. public @interface TestProvider {
  5. String value();
  6. }
  7. public interface TestConnector {
  8. }
  9. @TestProvider(&quot;TestConnector1&quot;)
  10. @Stateless
  11. public class Test1 implements TestConnector {
  12. }
  13. @Default
  14. @TestProvider(&quot;TestConnector2&quot;)
  15. @Stateless
  16. public class Test12 implements TestConnector {
  17. }
  18. @Stateless
  19. public class TestFactory {
  20. @Inject
  21. @Any
  22. private Instance&lt;TestConnector&gt; testConnectors;
  23. public TestConnector getConnector(String name) {
  24. ...
  25. }
  26. public Set&lt;String&gt; listAllTestConnectorNames(){
  27. try {
  28. Set&lt;String&gt; connectors = new HashSet&lt;String&gt;();
  29. this.testConnectors.forEach(con -&gt; {
  30. System.out.println(con.getClass().getName());
  31. for(Annotation x : con.getClass().getAnnotations()) {
  32. if(x instanceof TestProvider) {
  33. String name = ((TestProvider) x).value();
  34. System.out.println(name);
  35. connectors.add(name);
  36. }
  37. }
  38. this.testConnectors.destroy(con);
  39. });
  40. return connectors;
  41. } catch(Exception e) {
  42. ...
  43. }
  44. }

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标志,并且通常扩展了它们代理的类。我认为这不是一种保证,但在许多版本和多年的时间里都是如此。

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

  1. Class<?> c = proxyClass;
  2. while (c.isSynthetic()) {
  3. c = c.getSuperclass();
  4. }
  5. // 现在 c 是“真实”类
  6. 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:

  1. Class&lt;?&gt; c = proxyClass;
  2. while (c.isSynthetic()) {
  3. c = c.getSuperclass();
  4. }
  5. // Now c is the &quot;real&quot; class
  6. 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:

确定