正如我们在您自己的回答下的讨论中所解释的那样,我怀疑您的应用程序设计是否真的有意义,但对于它的价值,我已经使用AspectJ's annotation processing capability introduced in version 1.8.2 为您准备了一个解决方案。此解决方案是我在another StackOverflow answer 中针对更复杂的案例所描述的简化版本。
这是我的 Eclipse 布局,其中包含两个源文件夹和一个执行两阶段编译过程的 Windows 批处理文件,
- 首先编译一个 APT 处理器,负责为每个带注释的类创建一个方面
- 然后在下一个 AspectJ 编译步骤期间将此处理器实际应用到您的 Java 源代码。
这是我的目录布局的截图:
如您所见,类Application不能被Eclipse直接编译,您确实需要使用批处理文件。
标记注释:
注意,这个类必须存储在 src_apt 中才能对
稍后注释处理器EntityProcessor。
package de.scrum_master.app;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Entity {}
两个带注释的示例实体:
package de.scrum_master.app;
@Entity
public class User {}
package de.scrum_master.app;
@Entity
public class Group {}
驱动程序应用:
此应用程序依赖 APT 完成其工作,然后才能真正看到所使用的静态方法。
package de.scrum_master.app;
public class Application {
public static void main(String[] args) {
User.filter();
Group.filter();
}
}
方面打印方法签名:
这是原始方面的简化版本,仅打印方法签名,不声明任何父方法或静态方法。这只是为了以后得到更好的日志输出:
package de.scrum_master.aspect;
public aspect LogAspect {
pointcut staticFilter() :
call(public static * filter());
before() : staticFilter(){
System.out.println(thisJoinPoint);
}
}
注释处理器:
这个注解处理器搜索用@Entity注解的类,并创建一个aspect,为每个类引入一个静态方法filter()。
package de.scrum_master.app;
import java.io.*;
import java.util.*;
import javax.tools.*;
import javax.annotation.processing.*;
import javax.lang.model.*;
import javax.lang.model.element.*;
@SupportedAnnotationTypes(value = { "*" })
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class EntityProcessor extends AbstractProcessor {
private Filer filer;
@Override
public void init(ProcessingEnvironment env) {
filer = env.getFiler();
}
@Override
public boolean process(Set<? extends TypeElement> elements, RoundEnvironment env) {
env.getElementsAnnotatedWith(Entity.class).stream()
.filter(annotatedClass -> annotatedClass.getKind() == ElementKind.CLASS)
.forEach(annotatedClass -> {
String packageName = annotatedClass.getEnclosingElement().toString().substring(8);
String className = annotatedClass.getSimpleName().toString();
String aspectName = "ORMAspect_" + className;
String aspectSource = createAspectSource(packageName, className,aspectName);
writeAspectSourceToDisk(packageName, aspectName, aspectSource);
});
return true;
}
private String createAspectSource(String packageName, String className, String aspectName) {
StringBuilder aspectSource = new StringBuilder()
.append("package " + packageName + ";\n\n")
.append("import java.util.Collections;\n")
.append("import java.util.List;\n\n")
.append("public aspect " + aspectName + " {\n")
.append(" public static List<Object> " + className + ".filter() {\n")
.append(" System.out.println(\"Called filter method!\");\n")
.append(" return Collections.emptyList();\n")
.append(" }\n")
.append("}\n");
return aspectSource.toString();
}
private void writeAspectSourceToDisk(String packageName, String aspectName, String aspectSource) {
try {
JavaFileObject file = filer.createSourceFile(packageName + "." + aspectName);
file.openWriter().append(aspectSource).close();
System.out.println("Generated aspect " + packageName + "." + aspectName);
} catch (IOException ioe) {
// Message "already created" can appear if processor runs more than once
if (!ioe.getMessage().contains("already created"))
ioe.printStackTrace();
}
}
}
注解处理器的服务描述符:
这是META-INF/services/javax.annotation.processing.Processor的内容:
de.scrum_master.app.EntityProcessor
执行两阶段编译的批处理文件:
此批处理文件执行我在回答开头所描述的内容。请确保根据需要调整变量 SRC_PATH 和 ASPECTJ_HOME。
@echo off
set SRC_PATH=C:\Users\Alexander\Documents\java-src\SO_AJ_ITDStaticMethods
set ASPECTJ_HOME=C:\Program Files\Java\AspectJ
echo Building annotation processor
cd "%SRC_PATH%"
rmdir /s /q bin
del /q processor.jar
set CLASSPATH=%ASPECTJ_HOME%\lib\aspectjrt.jar
call "%ASPECTJ_HOME%\bin\ajc.bat" -1.8 -sourceroots src_apt -d bin
jar -cvf processor.jar -C src_apt META-INF -C bin .
echo.
echo Generating aspects and building project
rmdir /s /q bin .apt_generated
set CLASSPATH=%ASPECTJ_HOME%\lib\aspectjrt.jar;processor.jar
call "%ASPECTJ_HOME%\bin\ajc.bat" -1.8 -sourceroots src -d bin -s .apt_generated -inpath processor.jar -processor de.scrum_master.app.EntityProcessor -showWeaveInfo
echo.
echo Running de.scrum_master.app.Application
java -cp bin;"%ASPECTJ_HOME%\lib\aspectjrt.jar" de.scrum_master.app.Application
运行批处理文件时的控制台日志:
C:\Users\Alexander\Documents\java-src\SO_AJ_ITDStaticMethods>compile_run.bat
Building annotation processor
Manifest wurde hinzugefügt
Eintrag META-INF/ wird ignoriert
META-INF/services/ wird hinzugefügt(ein = 0) (aus = 0)(0 % gespeichert)
META-INF/services/javax.annotation.processing.Processor wird hinzugefügt(ein = 36) (aus = 38)(-5 % verkleinert)
de/ wird hinzugefügt(ein = 0) (aus = 0)(0 % gespeichert)
de/scrum_master/ wird hinzugefügt(ein = 0) (aus = 0)(0 % gespeichert)
de/scrum_master/app/ wird hinzugefügt(ein = 0) (aus = 0)(0 % gespeichert)
de/scrum_master/app/Entity.class wird hinzugefügt(ein = 293) (aus = 200)(31 % verkleinert)
de/scrum_master/app/EntityProcessor.class wird hinzugefügt(ein = 5679) (aus = 2476)(56 % verkleinert)
Generating aspects and building project
Generated aspect de.scrum_master.app.ORMAspect_Group
Generated aspect de.scrum_master.app.ORMAspect_User
Running de.scrum_master.app.Application
call(List de.scrum_master.app.User.filter())
Called filter method!
call(List de.scrum_master.app.Group.filter())
Called filter method!
等等!最后 4 行显示了您希望看到的内容:在带注释的目标类中显式声明的静态方法。享受吧!