4

目前我创建了一个插件,执行时需要从项目工件中访问类并检索注释。

/**
 * Generate document for services
 * 
 * @author Ali Irawan
 * 
 * @goal doc
 * @requiresDependencyResolution compile
 * @phase generate-sources
 */
public class GeneratePlugin extends AbstractMojo {

    /**
     * project
     * 
     * @parameter expression = "${project}";
     */
    protected MavenProject project;

    /**
     * scanPackage
     * 
     * @parameter
     */
    private String scanPackage;

    @Override
    public void execute() throws MojoExecutionException {
        getLog().info("My Maven Plugin Started");
        getLog().info("Scanning package: " + scanPackage);

        // PluginDescriptor pluginDescriptor = (PluginDescriptor) super.getPluginContext().get("pluginDescriptor");
        try {
            ClassLoader original = Thread.currentThread().getContextClassLoader();

            Collection urls = new ArrayList();

            Set<Artifact> artifacts = project.getArtifacts();
            Iterator<Artifact> iterator = artifacts.iterator();
            while(iterator.hasNext()){
                Artifact entry = iterator.next();
                urls.add(entry.getFile().toURI().toURL());
            }

            urls.add(new File(project.getBuild().getOutputDirectory()).toURI().toURL());

            Thread.currentThread().setContextClassLoader(new URLClassLoader((URL[]) urls.toArray(new URL[urls.size()]),original));

            ClassLoader loader = Thread.currentThread().getContextClassLoader();
            Class clazz = loader.loadClass("com.goijo.mona.services.AuthenticationService");
            getLog().info("Class name: " + clazz.getName());

            // This always return 0, don't know why ?
            getLog().info("Annotation : " + clazz.newInstance().getClass().getAnnotations().length);

            // Restore class loader
            Thread.currentThread().setContextClassLoader(original);

            getLog().info("MyMaven Plugin Stopped");
        } catch (Exception e) {
            e.printStackTrace();
            getLog().error(e.getMessage());
        }
    }


}

然后我在其他项目中使用这个插件

<plugin>
    <groupId>com.my</groupId>
    <artifactId>my-maven-plugin</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <configuration>
        <scanPackage>com.my.services</scanPackage>
    </configuration>
</plugin>

当我尝试使用执行 mvn 目标时

mvn my:doc

它产生这个输出

[INFO] Scanning package: com.goijo.mona.services
[INFO] Class name: com.my.services.AuthenticationService
[INFO] Annotation : 0

任何人都可以帮助为什么注释总是 0 因为我的类 com.my.services.AuthenticationService 已经被注释了

@InfoIn( ... )
public class AuthenticationService {

}

并且注释已经设置了 RetentionPolicy

@Target(value=ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface InfoIn {

    public Info[] value();

}
4

1 回答 1

1

问题的根源在于加载外部类文件时使用的 ClassLoader。以下代码应该可以解决您的问题...我编写了一个类似的 Maven 插件:

// The outputDirectory is the ${project.build.directory} the Maven plugin is executing in
File classesDirectory = new File(outputDirectory.getAbsolutePath() + "/classes"); 

URL classesUrl = classesDirectory.toURI().toURL();
URL[] classesUrls = new URL[]{classesUrl}; 

// Make sure to use the URLClassLoader, using the simple ClassLoader WILL NOT WORK for reading the annotations       
URLClassLoader classLoader = URLClassLoader.newInstance(classesUrls, getClass().getClassLoader());

// Load our remote class file found out in the "/classes" directory
Class classObject = classLoader.loadClass("com.my.services.AuthenticationService"); 

// Check to make sure the class has the annotation
if(classObject.isAnnotationPresent(InfoIn.class)) 
{
    // Get the annotation and print the value
    InfoIn annotation = (InfoIn)classObject.getAnnotation(InfoIn.class);
    System.out.println("Annotation value is: " + annotation.value());
}

我希望这会有所帮助。

于 2016-03-10T20:15:32.540 回答