Spring AOP和Spring JPA,执行切面

3

我一直在编写一个方面,它可以操作我的一些JPA实体获取器。它应该根据客户区域设置重新格式化返回的文本。因为并非所有的获取器都应该被重新格式化,所以我引入了一个注释@ReFormat

问题是,当我将其建议给JPA实体时,我的方面从未被拦截,但对于非JPA实体它却可以正常工作(当我通过复制构造函数创建自己的实体对象时它可以工作)。

我的注释:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface ReFormat {

}

我的任务:

@Aspect
public class ReFormatAspect {
    @AfterReturning(pointcut = "@annotation(com.path.ReFormat)", returning = "response")
    public Object formatter(JoinPoint joinPoint, Object response) {
       return response;
    }
}

现在,在我的MVC控制器中(或除Spring Data之外的任何其他位置),这个方面都被成功拦截,但对于我的实体却没有。

@Entity
@Table(name = "place", schema = "db")
public class TestEntity {

   @Id
   @Column(name = "id")
   protected long id;

   @Column(name = "about", columnDefinition = "TEXT DEFAULT NULL")
   protected String about;

   @ReFormat
   public String getAbout() {
       return this.about;
   }

当调用getAbout方法时,我预计会发生降点,但实际上却没有出现。

考虑到上述事实,我认为JPA(Hibernate)可能通过CGLib或javassist覆盖了任何拦截器。

注意:我将此放在我的上下文中。

<context:annotation-config />
<context:spring-configured />
<aop:aspectj-autoproxy proxy-target-class="true" />

那么问题确切是什么,我如何拦截实体内的任何方法?
我知道这应该是视图层的工作,但我仍然需要知道为什么:D
3个回答

3

您的实体不是由Spring管理的,而是由底层的JPA实现管理的。因此,Spring无法将它们包装在代理中并提供所需的行为。

没有Spring的解决方法。Hibernate可能有一些拦截器工具(在创建实体时包装实体),但我不知道它。也许可以扩展EmptyInterceptor


2

你可以始终使用AspectJ并在编译时调用你的切面。但是这种方式将无法访问Spring DI容器。


1
可以将AspectJ切面与Spring DI容器一起使用。 Spring AOP 文档表示:
“域对象通常属于此类别,因为它们通常是使用 new 操作符编程创建的,或者由 ORM 工具作为数据库查询的结果创建的。”
我创建了一个GitHub 项目,在其中使用您的 @ReFormat 注释对带有 @Entity 注释的 bean 的方法进行注释。为了能够在 AspectJ 切面中使用 DI,您需要使用 aspectOf() 方法。这甚至可以在 JavaConfig 中实现。因此,您根本不必使用 XML 配置。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接