gpt4 book ai didi

java - AspectJ - 继承的 'parents' 类上的切入点

转载 作者:太空宇宙 更新时间:2023-11-04 12:13:00 24 4
gpt4 key购买 nike

目标:调用类(class)的static filter()方法来 self 的任何一个 @Entity类。返回List<Object 。获取正确的类调用者类型。例如,当我调用filter()时来自User我想上的课User作为调用者类(不是拥有原始静态方法的类)。

这个filter()方法在 ORMEntity :

public static List<Object> filter(){
System.out.println("Called filter method!");
return Collections.emptyList();
}

我写了这个方面:

public privileged aspect OrmAspect {

//Extends ORMEntity when class marked with @Entity
declare parents : (@Entity *) extends ORMEntity;

//Getting filter() calls from anywhere
//This pointing to ORMEntity.filter()
pointcut staticFilter() : call(* *.filter());

before() : staticFilter(){
System.out.println(">>"+thisJoinPoint);
}

然后我可以从我的 main 方法中编写这样的代码:

User.filter();

用户是一个简单的bean @Entity注释。

这是这样工作的:

  1. 编译器看到 filter()方法来自User类(class)。好的。
  2. filter() 的切入点仅在ORMEntity.filter()上即使User extends ORMEntity (然后filter()方法)。不行。

之前的输出filter()连接点:

System.out.println(">>"+thisJoinPoint.getSignature().getDeclaringType());

ORMEntity而不是User这是我所期望的。

如何获得User类继承static filter()方法 ?或者在 declare parent 上有一个切入点与 AspectJ?

最佳答案

正如我们在您自己的回答下的讨论中所解释的那样,我怀疑您的应用程序设计是否真的有意义,但就其值(value)而言,我已经使用 AspectJ's annotation processing capability introduced in version 1.8.2 为您准备了一个解决方案。 。该解决方案是我在 another StackOverflow answer 中描述的更复杂情况的简化版本。 .

这是我的 Eclipse 布局,其中包含两个源文件夹和一个执行两阶段编译过程的 Windows 批处理文件,

  • 首先编译一个 APT 处理器,负责为每个带注释的类创建一个方面
  • 然后在下一个 AspectJ 编译步骤中实际将此处理器应用到您的 Java 源代码。

这是我的目录布局的屏幕截图:

Eclipse directory layout

如您所见,类 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 注释的类,并创建一个方面,为每个类引入一个静态方法 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_PATHASPECTJ_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 行显示了您想要看到的内容:在带注释的目标类中显式声明的静态方法。享受吧!

关于java - AspectJ - 继承的 'parents' 类上的切入点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39692158/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com