Общий вопрос
У меня есть два проекта A и B; B имеет зависимость от A. Я хочу сгенерировать некоторый код в B с помощью обработчика аннотации, основанный на аннотации на объектах в A. Когда я запускаю компиляцию с правильной реализацией процессора, выбираются только аннотированные объекты из B.
Я понимаю, что сканирование других JAR файлов должно быть отключено по умолчанию, потому что вы обычно не хотите выполнять аннотирование для всех ваших зависимостей. Я также понимаю, что может быть невозможно сделать то, что я хочу сделать из-за магии компилятора, о которой я не очень много знаю, но я надеюсь, что это не так.
Конкретный случай
Мои проекты называются DB и WEB. WEB, очевидно, зависит от DB для доступа к JPA; это настроено в Maven. Из-за ряда архитектурных вариантов, DB должен оставаться отдельным JAR. БД не использует Spring, за исключением некоторых аннотаций, которые потребляются WEB; WEB использует Spring MVC.
Я пытаюсь создать интерфейсы CrudRepository
для всех моих объектов JPA с помощью обработчика аннотаций. Предполагается, что объекты @Repository
входят в пакет 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. Я также опасаюсь конфигурации, которая может потребоваться для выполнения этой работы.
UPDATE
Дополнительная информация: я использую плагин maven-processor-plugin, который я проверил, чтобы хорошо работать в WEB-проекте для классов, которые там определены. Однако мне особенно нужны классы доступа, аннотированные в DB проекта зависимостей. Я рассмотрел метод AbstractProcessor::getSupportedOptions
, но мне непонятно, что я могу там сделать.
Конфигурация Maven:
<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>
SUGGESTION
Еще одна случайная мысль, которую я имел, заключалась в том, чтобы запустить процесс JavaCompiler
для проекта БД в WEB, но как бы я ввел свой Processor
?