gpt4 book ai didi

java - 使用 java.lang.reflection 的构造函数的 AspectJ 切入点

转载 作者:行者123 更新时间:2023-11-30 09:22:48 24 4
gpt4 key购买 nike

以下示例是对实际问题的简化,因为它试图尽可能地简化 is。

我有一个 java 接口(interface)和几个实现该接口(interface)的对象,例如:

public interface Shape{
public void draw();
public void erase();
public boolean isDrawn();
}

public class Square implements Shape{
@Override
public void draw(){
//TODO: method implementation
}

@Override
public void erase(){
//TODO: method implementation
}

Override
public boolean isDrawn(){
//TODO: method implementation
return false;
}
}

public Triangle implements Shape{
//same as above
}

public Circle implements Shape{
//same as above
}

这是我的程序结构。通过使用 AspectJ,我想要一个映射来保存实现该接口(interface)的每个对象。为此,我试图通过使用以下方面来捕获构造函数:

public aspect ShapeHolderAspect{
private Map<Integer, Shape> map = new HashMap<>();
private int count = 0;

pointcut shapeInit(): call((Shape+).new(..));

Object around(): shapeInit() {
System.out.println("capturing new");

Shape shapeType = (Shape)proceed();
map.put(++count, shapeType);
return shapeType;
}
}

如果我使用以下场景创建一个 Shape,此代码将起作用:

public static void main(String[] args){
Shape myShape = new Circle();
}

但是,我使用的是 java 语言反射,所以从技术上讲,我不调用"new"构造函数。相反,我找到了包的路径,并创建了传递带有类名的字符串的对象:

public static void main(String[] args){
String shapeClassName = args[0];
Class<?> classType = Class.forName("myPackage.figures" + "." + shapeClassName);
Shape myShape =(Shape)classType.getConstructor().newInstance();
}

通过这种方式,AspectJ 无法检测到我正在创建形状。我该如何解决这个问题?

最佳答案

新的、更好的版本:

好吧,虽然下面的旧版本实际上捕获了所有构造函数的执行,但是关于构造函数执行的 around 建议返回 null,因为所讨论的对象尚未初始化。所以你最终会在你的方面得到一个空指针映射。为了解决这个问题,您需要将 this() 绑定(bind)到一个变量(示例代码使用默认包名称):

public class Application {
public static void main(String[] args) throws Exception {
new Circle().draw();
((Shape) Class.forName("Triangle").getConstructor().newInstance()).isDrawn();
((Shape) Class.forName("Square").getConstructor().newInstance()).erase();
}
}
import java.util.HashMap;
import java.util.Map;

public aspect ShapeHolderAspect {
private Map<Integer, Shape> map = new HashMap<Integer, Shape>();
private int count = 0;

after(Shape shape): execution(Shape+.new(..)) && this(shape) {
System.out.println(thisJoinPointStaticPart);
map.put(++count, shape);
}

after() : execution(* Application.main(..)) {
System.out.println("\nList of shapes:");
for (int key : map.keySet())
System.out.println(" " + key + " -> " + map.get(key));
}
}

输出看起来像这样:

initialization(Circle())
initialization(Triangle())
initialization(Square())

List of shapes:
1 -> Circle@1a2961b
2 -> Triangle@12d03f9
3 -> Square@5ffb18

顺便说一句,如果你绝对需要 around 建议,因为你想在创建对象之前做其他事情,它看起来像这样:

void around(Shape shape): execution(Shape+.new(..)) && this(shape) {
System.out.println(thisJoinPointStaticPart);
proceed(shape);
map.put(++count, shape);
}

旧的、不完整的版本:

很简单,只拦截构造函数执行而不是调用:

pointcut shapeInit(): execution(Shape+.new(..));

这样您就可以编织到被调用代码(被调用者)中,而不是调用代码(调用者)中。因此,调用者发出反射调用还是正常调用都没有关系。

关于java - 使用 java.lang.reflection 的构造函数的 AspectJ 切入点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16318426/

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