当前位置: 首页 > 面试题库 >

Spring AOP-在调用setter之前获取旧的字段值

庾远航
2023-03-14
问题内容

亲爱的所有人,我目前正在将Spring AOP(v4)和AspectJ与Load-Time-Weaver一起使用。

我目前正在寻找一种将脏标志机制添加到我的bean中的方法。因此,尽管II在使用我的bean的setter之前使用AOP来调用方法。我已经实现了,但是如何在修改之前访问旧的字段值?还是有一种获取字段名称的方法,以便我可以在调用setter之前先调用getter?

有人可以在这里为我提供一些示例,以使切入点/建议看起来像是如何将其作为参数传递的吗?

@Aspect
public class MyAspect {

  @Before("execution(* foo.*.set*(..))") 
  public void beforeSetterCalled(JoinPoint joinPoint){
    System.out.println("beforeSetter");
  }
}

不幸的是,Spring AOP似乎不支持“ set()”字段切入点构造,这是正确的吗?还是存在某种使用方式?

感谢您的任何帮助。


问题答案:

我建议将完整的AspectJ与set()切入点结合使用,以获得有效的解决方案。但是,如果您不介意使用缓慢而丑陋的解决方案来进行反射,那么您也可以执行以下操作:

package de.scrum_master.app;

public class Person {
    private int id;
    private String firstName;
    private String lastName;

    public Person(int id, String firstName, String lastName) {
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
    }

    public int getId() { return id; }
    public String getFirstName() { return firstName; }
    public String getLastName() { return lastName; }

    public void setId(int id) { this.id = id; }
    public void setFirstName(String firstName) { this.firstName = firstName; }
    public void setLastName(String lastName) { this.lastName = lastName; }

    @Override
    public String toString() { return "Person [" + id + ", " + firstName + " " + lastName + "]"; }

    public static void main(String[] args) {
        Person albert = new Person(1, "Albert", "Camus");
        Person audrey = new Person(2, "Audrey", "Hepburn");
        System.out.println(albert);
        System.out.println(audrey);
        System.out.println();
        albert.setId(8);
        albert.setLastName("Einstein");
        audrey.setId(9);
        audrey.setLastName("Tautou");
        System.out.println();
        System.out.println(albert);
        System.out.println(audrey);
    }
}



package de.scrum_master.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.SoftException;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class SetterInterceptor {
    @Before("execution(* set*(*)) && target(instance) && args(newValue)")
    public void beforeSetterCalled(JoinPoint thisJoinPoint, Object instance, Object newValue) {
        String methodName = thisJoinPoint.getSignature().getName();
        try {
            System.out.println(
                methodName.substring(3) + ": " +
                instance
                    .getClass()
                    .getMethod(methodName.replaceFirst("set", "get"))
                    .invoke(instance) +
                " -> " + newValue
            );
        } catch (Exception e) {
            throw new SoftException(e);
        }
    }
}

控制台日志:

Person [1, Albert Camus]
Person [2, Audrey Hepburn]

Id: 1 -> 8
LastName: Camus -> Einstein
Id: 2 -> 9
LastName: Hepburn -> Tautou

Person [8, Albert Einstein]
Person [9, Audrey Tautou]


 类似资料:
  • 当使用aspectj我有以下切入点: 如果指定了字段中已经存在的相同值,也会调用此切入点。有没有有效的方法在设置和比较之前获取值,以便只有在有“真实”变化时才调用我的打印?

  • 问题内容: 我正在将图像文件上传到存储服务器。上传之前,我应该编写文件名,其中包含AUTOINCREMENT VALUE(例如12345_filename.jpg)。 在插入数据库之前如何获得自动增量值? 我只看到一种解决方案 插入空行 得到它的自动增量值 删除该行 使用第1页中的自动增量值将行插入实际数据 还有其他解决方案吗? 谢谢 问题答案: 完成插入后,自动增量值由数据库本身生成;这意味着您

  • 有一个类内部有另一个静态类。Jackson在反序列化JSON时调用setter。但某些设置器不能按预期工作。 类定义: 输出: 设置名称caled,名称=黑暗之塔

  • 问题内容: 我有很多代码, 调用时处理器很小,有时会导致性能问题(100毫秒),因此我想知道当前等待对象释放的线程是什么。 我想在调用之前打印所有等待对象释放的线程 问题答案: 是否所有线程都在资源上等待相同的条件?如果是,则可以尝试替换,尽管实际上不建议这样做。AFAIK,无法“检索”在给定对象上等待的所有线程的列表(尽管您可以通过编程方式获取进程的线程转储并查看线程,但是我敢肯定那不是您拥有的

  • 问题内容: 我想获得一个空格之前的字段中的所有字符 例如,如果是 我要它回来 该选择语句是什么样的? 问题答案: 请注意,如果所讨论的字符串不包含空格,则将返回一个空字符串。