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