不受 Spring 管理的域对象上的 AspectJ 切入点表达式

AspectJ Pointcut Expression on domain objects not managed by Spring

问题: Spring 切入点表达式 运行 可以在非托管 spring 组件(例如域对象)上使用吗?从我的实验来看似乎没有,那么在常规对象上 运行 切入点表达式的最佳方法是什么?

我创建了自定义注释名称@Encrypt,以便在域对象中的字段顶部使用它时,该字段被发送到 Web 服务并自动加密。

我首先从方法级别注释开始,发现切点表达式不适用于不受 Spring 管理的对象,它必须是 spring bean。

1. Spring 方面: 检查自定义注释 @Encrypt 并打印出来。

@Aspect
public class EncryptAspect {

    @Around("@annotation(encrypt)")
    public Object logAction(ProceedingJoinPoint pjp, Encrypt encrypt)
            throws Throwable {

        System.out.println("Only encrypt annotation is running!");
        return pjp.proceed();
    }
}

2。自定义注释:

@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)

public @interface Encrypt
{
    // Handled by EncryptFieldAspect
}

3。使用注释的域对象

public interface CustomerBo {
    void addCustomerAround(String name);
}

public class CustomerBoImpl implements CustomerBo {    
    @Encrypt
    public void addCustomerAround(String name){
        System.out.println("addCustomerAround() is running, args : " + name);
    }
}

4.调用

        ApplicationContext appContext = new ClassPathXmlApplicationContext("http-outbound-config.xml");
//      CustomerBoImpl customer = new CustomerBoImpl(); --> Aspect is not fired if object is created like this.
        CustomerBo customer = (CustomerBo) appContext.getBean("customerBo"); // Aspect Works
        customer.addCustomerAround("test");

对于您的第一个问题(“可以 Spring 切入点表达式 运行 在非托管 spring 组件(例如域对象)上吗?”)答案是否定的。 Spring reference manual has a chapter that exactly explains how Spring AOP works and why it won't work in that case.

我看到的选项是(按我最有可能处理此问题的方式排序):

  1. 删除方面并将此不变量封装在创建 CustomerBo 的服务或工厂中。如果 CustomerBoImpl 是不可变的,那将是最好的,这样您就不必担心它会被解密并留在不正确的状态。
  2. 如果您正在使用 Java 持久性 API (JPA) 来持久化您的域对象,并且在将它们保存到数据库之前加密到 运行 是可以的,您可能想使用 listeners。(注意:link 导致 Hibernate 的文档,它是 JPA 的实现之一)
  3. 核选项 - 实际上切换到使用 AspectJ,它可以向构造函数、字段值更改等引入建议