非Spring管理的域对象上的AspectJ Pointcut Expression

Him*_*dar 3 java spring annotations spring-aop

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

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

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

1. Spring Aspect:检查自定义注释@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();
    }
}
Run Code Online (Sandbox Code Playgroud)

2.自定义注释:

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

public @interface Encrypt
{
    // Handled by EncryptFieldAspect
}
Run Code Online (Sandbox Code Playgroud)

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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");
Run Code Online (Sandbox Code Playgroud)

Apo*_*psa 5

对于第一个问题(“ Spring切入点表达式可以在非托管Spring组件(例如域对象)上运行吗?”),答案是否定的。Spring参考手册的一章准确地解释了Spring AOP是如何工作的,以及为什么在这种情况下它不能工作

我看到的选项是(按照我最有可能解决此问题的方式排列):

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