简体   繁体   English

Class 通过反射检查 API.自定义注解的使用

[英]Class inspection via reflection API. Use of custom annotations

I have done my research before asking but no luck.我在询问之前已经完成了我的研究,但没有运气。

I have a StartUp Singleton bean.我有一个 StartUp Singleton bean。 In this bean I have an @Inject @Any Instance.在这个 bean 中,我有一个 @Inject @Any 实例。 I loop all the implementations and try to check if the class is annotated with a custom annotation.我循环所有实现并尝试检查 class 是否使用自定义注释进行注释。 All the implementations(all the classes that I want to inspect) are Stateful or Stateless beans.所有实现(我要检查的所有类)都是有状态或无状态 bean。 Sometime the class I want is found and I can perform getClass().isAnnotationPresent(ClassNameAnnotation.class)有时找到我想要的 class,我可以执行 getClass().isAnnotationPresent(ClassNameAnnotation.class)

Most of the times I get a proxy object and in this case I cannot perform the above check.大多数时候我得到一个代理 object,在这种情况下我无法执行上述检查。 I cannot find a way to get the real object. I have tried to get the SuperClass but not luck.我找不到获得真正的 object 的方法。我曾尝试获得 SuperClass 但不是运气。 I will attach some of the code so you can have a better idea.我将附上一些代码,以便您有一个更好的主意。

@Singleton
@Startup
public class CacheLoader {

    @Inject
    @Any
    private Instance<ClassNameA> aClasses;

   .......

    @Lock(LockType.READ)
    public void evaluate() {

        if (!aClasses.isUnsatisfied()) {
            for (ClassNameA className : aClasses) {
                if (className.getClass().isAnnotationPresent(ClassNameAnnotation.class)) {
                    ....
                }
            }
        }
    }

}

I tried to use the SuperClass of the proxy object but it does not return what I want.我尝试使用代理 object 的 SuperClass,但它没有返回我想要的内容。 I tried also via Proxy.getInvocationHandler().我也尝试通过 Proxy.getInvocationHandler()。 Even when I check the methods Proxy.isProxyClass(getClass()) or isSynthetic() does not return that the object is a proxy.即使我检查方法 Proxy.isProxyClass(getClass()) 或 isSynthetic() 也不会返回 object 是代理。

Thank you!谢谢!

I think you would be better served by using a CDI Portable Extension, rather than a Singleton EJB.我认为使用 CDI 可移植扩展而不是 Singleton EJB 会更好地为您服务。 A couple of reasons几个原因

  • In CDI, everything is a proxy.在 CDI 中,一切都是代理。 So like some of the commenters have said, using reflection would be very fragile as it's not part of the spec.所以就像一些评论者所说的那样,使用反射会非常脆弱,因为它不是规范的一部分。 You're dealing with classes that are defined at runtime.您正在处理在运行时定义的类。 It may work if you tie yourself to implementation-specific details, but it could break between releases of your CDI container.如果您将自己与特定于实现的细节联系起来,它可能会起作用,但它可能会在您的 CDI 容器版本之间中断。

  • The CDI Container will do all of the annotation scanning for you:) CDI 容器将为您完成所有注释扫描:)

  • A portable extension runs on startup, before other stuff starts flying around your app一个可移植的扩展在启动时运行,在其他东西开始在你的应用程序周围飞来飞去之前

A google search gave me this guide, but there are lots of them: https://www.baeldung.com/cdi-portable-extension谷歌搜索给了我这个指南,但有很多: https://www.baeldung.com/cdi-portable-extension

I think you would want to hook in processAnnotatedType() if you're modifying the bean declarations, or afterBeanDiscovery() if you're just documenting them as you said.如果您正在修改 bean 声明,我想您会想挂钩processAnnotatedType() ,或者如果您只是按照您所说的记录它们,则afterBeanDiscovery()

We actually have a CDI Portable Extension we use internally that does some config magic for environments.我们实际上有一个我们在内部使用的 CDI 便携式扩展,它为环境做了一些配置魔术。 One of the config params is an annotation that is not a qualifier annotation, which sounds like what you want... the CDI container can get you the type, from which you can inspect the annotations.配置参数之一是不是限定符注释的注释,这听起来像你想要的...... CDI 容器可以为你提供类型,你可以从中检查注释。

Finally, this is not directed related to your question but may be useful: If your annotations drive configuration through fields of the annotations, selecting them can be quite complicated because of how the Java type and inheritance system works with annotations.最后,这与您的问题无关,但可能有用:如果您的注释通过注释字段驱动配置,则选择它们可能会非常复杂,因为 Java 类型和 inheritance 系统如何使用注释。 You may benefit by using AnnotationLitreal in those cases.在这些情况下,您可能会受益于使用AnnotationLitreal Read up here on this useful utility class here: http://www.kurtsparber.de/?p=387在这里阅读这个有用的实用程序 class: http://www.kurtsparber.de/?p=387

EDIT: Another side note... even thought I think you should switch to a Portable Extension, you shouldn't need @EJB's Singleton Startup anymore: you can do this with pure CDI: https://rmannibucau.wordpress.com/2015/03/10/cdi-and-startup/编辑:另一个旁注......即使我认为你应该切换到便携式扩展,你不应该再需要@EJB的Singleton Startup:你可以用纯CDI做到这一点: https://rmannibucau.wordpress.com/2015 /03/10/cdi-和-启动/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM