在运行时读取所有使用特定注释修饰的类

时间:2014-08-20 01:30:59

标签: java reflection annotations cdi

我需要在运行时读取用特定注释(比如@HttpSecurity)修饰的所有类(接口)。扫描完毕后,我希望阅读并解析用注释装饰的类的字段(枚举字段)。例如。

@HttpSecurity
public interface MyHttpSecurityConfig {

public enum secure {
    @Path(pathGroup = "/*", pathName = "")
    @Authc
    @Form(errorPage = "/error.html", loginPage = "/login.html", restoreOriginalRequest = "")
    @Authz
    @AllowedRoles(roles = { "roleA", "roleB" })
    @AllowedGroups(groups = { "groupA" })
    @AllowedRealms(realms = { "realmA" })
    @Expressions(expressions = { "#{identity.isLoggedIn()}" })
    Admin
  }
}

可能有一个或多个用@HttpSecurity修饰的类/接口。 我的第一个要求是获取所有这些类,第二个要求是通过读取枚举字段上装饰的注释及其值来构建HttpSecurityBuilder。 第二个要求很好,可以使用反射完成。但是,我的问题是第一个要求。我想用JavaSE核心实现第一个要求,即不使用任何外部依赖,如谷歌反思。如有必要,可以假设我们具有要扫描类的包名称。以下是我做的事情cdi

2 个答案:

答案 0 :(得分:5)

您可以创建一个CDI扩展来观察CDI Annotations的扫描并创建自定义,如下例所示:

1)您需要使用@HttpSecurity

创建Qualifier
@Qualifier
@Retention(RUNTIME)
@Target({TYPE, METHOD, FIELD, PARAMETER})
public @interface HttpSecurity {}

2)您需要通过实现 javax.enterprise.inject.spi.Extension 接口来创建扩展:

    package net.mperon.cdi.extension;

    public class MyExtension implements Extension {

    private static final Logger log = LoggerFactory.getLogger(MyExtension.class);

    public <T> void processAnnotatedType(@Observes ProcessAnnotatedType<T> pat) {
        AnnotatedType<T> at = pat.getAnnotatedType();

        //if dont have you anotation, just continue
        if(!at.isAnnotationPresent(HttpSecurity.class)) {
            return;
        }

        //here you can read all annotation from object and do whatever you want:
        log.info("class: {}", at.getJavaClass());
        log.info("constructors: {}", at.getConstructors());
        log.info("fields: {}", at.getFields());
        log.info("methods: {}", at.getMethods());

        //and so more...

    }

}

3)您可以看到所有方法和属性here

4)最后,您需要在名为 javax.enterprise.inject.spi.Extension META-INF / services 下创建一个服务文件

5)在此文本文件中,您需要为扩展程序提供完整的类名称,例如:

net.mperon.cdi.extension.MyExtension

答案 1 :(得分:2)

不幸的是,Java并没有提供一种简单的方法来列出&#34; native&#34; JRE。我最喜欢的解决方案是Google Reflections库,但如果您不想使用它,还有其他方法。一种方法是找到有问题的jar或jar并扫描它们以获取类文件上的注释。这是通过以下方式实现的:

// Jars are really just zip files with a different name
ZipInputStream zip = new ZipInputStream(new FileInputStream("/path/to/jar/file.jar"));

for(ZipEntry entry=zip.getNextEntry(); entry!=null; entry=zip.getNextEntry()) {
    String name = entry.getName();

    // We only want class files
    if(name.endsWith(".class") && !entry.isDirectory()) {

        // Remove the .class extension
        name = name.substring(0, name.length() - 6);

        // Replace the slashes in the path with '.'
        name.replaceAll("/",".");

        // Get the class object so we can use reflection on it
        Class<?> cls = Class.forName(name);
    }        
}