- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
目标:调用类(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
注释。
这是这样工作的:
filter()
方法来自User
类(class)。好的。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 批处理文件,
这是我的目录布局的屏幕截图:
如您所见,类 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_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 行显示了您想要看到的内容:在带注释的目标类中显式声明的静态方法。享受吧!
关于java - AspectJ - 继承的 'parents' 类上的切入点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39692158/
我正在使用 aspectj 来拦截用 @Profile(description="something") 注释的方法 @Retention(RetentionPolicy.RUNTIME) @Targ
我对 Spring AOP 中的所有类都有一个切入点,例如 @Pointcut("执行(* com.company.app..*(..))") 现在我需要排除一个类 com.company.app.I
我对 Spring AOP 中的所有类都有一个切入点,例如 @Pointcut("执行(* com.company.app..*(..))") 现在我需要排除一个类 com.company.app.I
我想知道以下内容在切入点中意味着什么 after(FigureElement fe, int x, int y) returning: call(void FigureElement.
在开始之前,我想澄清一下,我目前对 AOP 术语的理解如下...... 方面是 AOP 等同于 OOP 中的类。 通知是 AOP 等价于 OOP 中的方法。 切入点是 AOP 等价于 OOP 中的“使
我将参与 android 设备驱动程序的开发。在准备过程中,我想掌握基础知识并为此提高我的技能。 过去 2 年我一直在使用 VB 和 JAVA,所以我对自己的 C 编程没有信心。 Linux 设备驱动
我想记录类列表(可能属于不同的包)中所有方法的条目。请注意,这些方法应该只属于指定的类。 我试过以下方法,但这些都不起作用 (1) 使用 if() 切入点这里报错 "incompatible numb
我正在使用 @AspectJ 样式来编写方面,以处理我们应用程序中的日志记录。基本上我有一个像这样设置的切入点: @Pointcut("call(public * com.example..*(..)
例如我有以下方法: public void method1(@MyAnnotation Object a, Object b..) { ... } public void method1(Obj
我正在寻找一种围绕类级别变量指定切入点的方法。像这样的东西: @Target(ElementType.METHOD) @Retention(RetentionPolicy.FIELD) @interf
如何编写一个切入点来触发方法,例如MyClass 上的所有 setter 都被执行,但该方法缺少一些特定的注释,例如@Ann1 和 @Ann2 最佳答案 import java.lang.annota
我在让各个方面正常工作时遇到一些问题。由于某种原因,它们似乎只有在我真正了解该方面的应用位置时才起作用。在四个切入点/建议中,只有最后一个匹配并输出任何内容。我在这里缺少什么? public aspe
我是 Spring AOP 触发器的新手。我的代码中有以下切入点触发器。当定义了所有四个切入点时,只有第一个切入点触发器 (com.src.a()) 正在工作,下面的其余切入点不会触发。但是当我在四个
使用加载时编织,纯 AspectJ。 我们有 2 个注释 @Time 和 @Count,以及一些带注释的方法。 @Time (name="myMethod1Time") @Count (name="m
这个问题已经有答案了: Java Aspect returned value to be used in the method (1 个回答) 已关闭 6 年前。 我想要 AOP 记录方法的返回值
我正在尝试围绕使用自定义注释注释的方法定义切入点。注释有一个参数,我想在切入点定义中包含一个检查。 这是注释: public @interface MyAnno { String[] types;
我正在使用 Spring AOP 进行日志记录。我想创建一个适用于除具有特定注释的方法之外的所有方法的切入点,但我不知道如何去做。我所发现的只是如何包含带有注释的方法。 最佳答案 示例注释: pack
/* 0 */ pointcut services(Server s): target(s) && call(public * *(..)) This pointcut, named services
我需要使用 AspectJ 向每个初始化对象注入(inject)一些方法。 我想用这个: pointcut vistaInjection(Object o) : initialization(
假设我有这样的方法: public void method(@CustomAnnotation("value") String argument) 是否有一个切入点表达式可以选择所有带有 @Custo
我是一名优秀的程序员,十分优秀!