我有两个项目A和B; B依赖于A.我想根据A中对象的注释在B中使用Annotation Processor生成一些代码。当我使用正确的Processor实现运行编译时,只会拾取B中带注释的对象。 / p>
我知道默认情况下必须禁用扫描其他JAR,因为您通常不希望对所有依赖项执行注释扫描。我也明白,由于编译魔术可能无法做我想做的事 - 我不太了解 - 但我希望它不是。
我的项目称为DB和WEB。 WEB显然依赖于DB的JPA访问;这是在Maven中配置的。由于许多架构选择,DB必须保持独立的JAR。除了WEB使用的一些注释之外,DB不使用Spring; WEB使用Spring MVC。
我尝试使用Annotation Processor为我的所有JPA实体生成CrudRepository
接口。 @Repository
对象应该放在WEB项目的repo
包中,因此它们可以在我的WEB应用程序中的任何地方与@Autowired
一起使用。我执行扫描的注释是@javax.persistence.Entity
,但我也尝试过自定义注释,结果相同。
@SupportedAnnotationTypes("javax.persistence.Entity")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class RepositoryFactory extends AbstractProcessor {
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
for (Element e : roundEnv.getElementsAnnotatedWith(Entity.class)) {
if (e.getKind() != ElementKind.CLASS) {
continue;
}
// TODO: implement logic to skip manually implemented Repos
try {
String name = e.getSimpleName().toString();
TypeElement clazz = (TypeElement) e;
JavaFileObject f = processingEnv.getFiler().
createSourceFile("blagae.web.repo." + name + "Repo");
try (Writer w = f.openWriter()) {
PrintWriter pw = new PrintWriter(w);
pw.println("package blagae.web.repo;");
pw.println("import org.springframework.data.repository.CrudRepository;");
pw.printf("import %s;\n", clazz.toString());
pw.println("import org.springframework.stereotype.Repository;");
pw.println("@Repository");
pw.printf("public interface %sRepo extends CrudRepository<%s, Long> {}\n", name, name);
pw.flush();
}
} catch (IOException ex) {
Logger.getLogger(RepositoryFactory.class.getName()).log(Level.SEVERE, null, ex);
}
}
return false;
}
}
理想情况下,我喜欢有人告诉我一个简单的注释
@ComponentScan(basePackages = "blagae.db.*")
但当然,我并不指望这一点,因为它可能会被记录在某处。作为一种解决方法,我可以将Spring依赖项添加到db并在那里生成类,但它们仅用于Spring MVC应用程序中。我也很担心可能需要的配置才能完成这项工作。
一些额外的信息:我使用maven-processor-plugin,我已经验证它在WEB项目中很好地适用于那里定义的类。但是,我特别希望在依赖项目DB中注释访问类。我已经研究了方法AbstractProcessor::getSupportedOptions
,但我不清楚我能在那里做什么。
Maven config:
<plugin>
<groupId>org.bsc.maven</groupId>
<artifactId>maven-processor-plugin</artifactId>
<version>2.2.4</version>
<configuration>
<processors>
<processor>blagae.utils.RepositoryFactory</processor>
</processors>
</configuration>
<executions>
<execution>
<id>process</id>
<goals>
<goal>process</goal>
</goals>
<phase>generate-sources</phase>
</execution>
</executions>
</plugin>
我的另一个随机想法是在WEB中为DB项目运行JavaCompiler
进程,但是如何注入Processor
?
答案 0 :(得分:6)
注释处理器适用于项目的编译阶段(在您的情况下为WEB),编译器编译此项目。当前项目的依赖关系已经编译,编译器(以及您的注释处理器)不会触及(或无法访问)第三方库(DB)。
您可以尝试将注释处理器提取到单独的项目/ jar中,并在WEB和DB项目中使用它。在这种情况下,注释处理器将在具体项目的编译阶段创建CrudRepository
。所有在DB项目中生成的类都将在WEB中提供。
答案 1 :(得分:4)
就个人而言,我会在一个单独的maven模块中提取注释处理器,并从WEB模块中添加一个依赖项。
然而,对于成功触发注释处理器而言,这并不重要。
为了使注释处理器正常工作,您必须提供两件事:
javax.annotation.processing.AbstractProcessor
类的类。META-INF/services
中。由于您提到目前没有生成类,我认为您错过了元文件。因此,打开您的WEB项目并导航到src/main/resouces
文件夹。在其中,您必须创建一个META-INF
文件夹,其中包含嵌套的services
文件夹。然后,在services
中创建一个名为 javax.annotation.processing.Processor
的文件。文件的内容应列出注释处理器的完全限定类名。如果有多个注释处理器,则完全限定的类名应位于不同的行上。但既然你只有一个,那么你就会有:
com.yourdomain.processor.RepositoryFactory
请注意,您必须使用注释处理器的实际完全确认的类名更改此行。
最后,你应该得到类似的结构:
此元文件很重要,因为否则编译器不会知道用户定义的注释处理器。拥有它,它将使用所有已注册的处理器。
之后,当您执行mvn clean install
时,所有模块都将被清理和构建。但是,由于编译器现在将知道您的注释处理器,它将触发它。所有生成的源将(默认情况下)位于target/generated-sources
文件夹中。此外,它们都将在您在注释过程中配置的包中,即blagae.web.repo
。
为了在代码中使用生成的源,您必须将targer/generated-sources
添加到项目类路径中。如果您不想依赖IDE来执行此操作,则可以通过将<build>
添加到类路径来扩展maven target/generated-sources
。类似的东西:
<build>
<resources>
...
<resource>
<directory>${project.build.directory}/generated-resources</directory>
</resource>
</resources>
</build>
答案 2 :(得分:-1)
在您的项目A中包含META-INF / beans.xml文件, 其中包含以下内容:
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee <a href="http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd">http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"</a>
version="1.1" bean-discovery-mode="all">
</beans>
并尝试一下。您应该使用JavaEE 7 / CDI 1.1。有关更多信息,请参阅Java EE 7 Deployment Descriptors。
您还可以参考此相关问题:How to @Inject object from different project module included as jar