As explained in our discussion under your own answer, I doubt that your application design really makes sense, but for what it is worth, I have prepared a solution for you using AspectJ's annotation processing capability introduced in version 1.8.2. This solution is a simplified version of what I have described for a much more complicated case in another StackOverflow answer.
Here is my Eclipse layout with two source folders and a Windows batch file performing a two-phase compilation process,
- first compiling an APT processor responsible for creating one aspect per annotated class
- and then actually applying this processor to your Java sources during the next AspectJ compilation step.
Here is a screenshot of my directory layout:

As you can see, class Application
cannot be directly compiled by Eclipse, you really need to use the batch file.
Marker annotation:
Attention, this class must be stored inside src_apt in order to be visible for
the annotation processor EntityProcessor
later.
package de.scrum_master.app;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Entity {}
Two annotated sample entities:
package de.scrum_master.app;
@Entity
public class User {}
package de.scrum_master.app;
@Entity
public class Group {}
Driver application:
This application relies on APT doing its job before it can actually see the static methods used.
package de.scrum_master.app;
public class Application {
public static void main(String[] args) {
User.filter();
Group.filter();
}
}
Aspect printing method signatures:
This is a simpilfied version of your original aspect, only printing method signatures, not declaring any parents or static methods. This is just in order to get nicer log output later:
package de.scrum_master.aspect;
public aspect LogAspect {
pointcut staticFilter() :
call(public static * filter());
before() : staticFilter(){
System.out.println(thisJoinPoint);
}
}
Annotation processor:
This annotation processor searches for classes annotated with @Entity
and creates one aspect introducing a static method filter()
for each of them.
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();
}
}
}
Service descriptor for annotation processor:
This is the content of META-INF/services/javax.annotation.processing.Processor:
de.scrum_master.app.EntityProcessor
Batch file performing two-phase compilation:
This batch file does what I described at the beginning of my answer. Please make sure you adjust variables SRC_PATH
and ASPECTJ_HOME
to your needs.
@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
Console log when running the batch file:
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!
Et voilà! The last 4 lines show what you want to see: static methods explicitly declared in your annotated target classes. Enjoy!