【问题标题】:Some doubts related to the AOP configuration in SpringSpring中AOP配置相关的一些疑惑
【发布时间】:2015-02-04 15:07:33
【问题描述】:

我正在学习 Spring Core 认证,我对 Spring 如何处理 AOP 有疑问。

阅读文档似乎了解在 Java 中获取 AOP 的方法有 2 种:

  1. 使用 AspectJ 将字节码修改用于切面编织提供了成熟的面向切面编程语言。 (所以在我看来,AspectJ 是一种不同的语言,可以与 Java 集成以提供 AOP 功能)。

  2. Spring AOP:用于使用动态代理进行方面编织而不是字节码修改的 Spring 框架。

所以我的疑惑主要有以下几点:

1) 阅读文档发现以下方法可以将 AOP 支持 添加到我的 Spring 应用程序中:

使用 JAVA 配置类:

@Configuration
@EnableAspectJAutoProxy
@ComponentScan(basePackages=“com.example”)
public class AspectConfig {
    ...
}

使用 XML 配置:

<beans>
    <aop:aspectj-autoproxy />
    <context:component-scan base-package=“com.example” />
</beans>

正如您在两种配置中看到的,都引用了 AspectJ

@EnableAspectJAutoProxy

<aop:aspectj-autoproxy />

为什么?如果 Spring 使用 Spring AOP 而不是 AspectJ 为什么我在 Spring 中配置 AOP 时会引用 AspectJ

2) 在前面的示例中,展示了两种配置 Spring 的方法:Java 配置类XML 配置。我知道存在第三种配置 Spring 应用程序的方法:使用注解。那么存在使用注解配置 AOP 的方法吗?

【问题讨论】:

    标签: java spring spring-mvc aop spring-aop


    【解决方案1】:

    我认为这些名称中引用了 AspectJ 的 Spring AOP 设置确实令人讨厌而不是有用。我能理解你为什么感到困惑。 Spring AOP 确实是与 AspectJ 不同的概念。正如您所说:Spring AOP 中的动态 JDK 或 CGLIB 代理与 AspectJ 中编译或加载期间的字节码检测。其他区别是:

    • AspectJ 编译时编织需要一个名为 Ajc 的特殊编译器。它基本上是一个 Eclipse Java 编译器 Ecj,由执行检测的切面编织器增强。相比之下,Spring AOP 在运行时创建动态代理。
    • 在 AspectJ 中有两种语法变体:原生的和基于注释的。前者更加优雅和富有表现力,是 Java 的超集,肯定需要 Ajc 来编译。后者使用Java注解,可以用Javac编译,但是需要Ajc(编译时)和编织中都包含的切面编织器代理 aspectjweaver.jar(加载时间)“完成”它们并使其在运行时可用。两种变体都需要包含在 aspectjrt.jar(非常小,用于运行时编译时编织方面)和 aspectjweaver.jar(更大,用于对于加载时编织,包含运行时和编织器)。
    • AspectJ 适用于任何 Java 类,它不需要甚至不知道 Spring 框架。 Spring AOP 需要 Spring 框架作为基础,您只能使用它来检测 Spring Beans/Components,而不是与 Spring 无关的 POJO。
    • AspectJ 更高效,因为它避免了代理。但是 Spring AOP 无论如何都是 Spring 框架的一个可选部分,所以如果你使用 Spring 并且只需要 Spring Beans 的方法执行拦截,那么使用它是非常有意义的。
    • Spring AOP 使用 AspectJ 切入点语法的一个子集。 也许这就是 Spring AOP 使用 AspectJ 引用的微妙原因,但我仍然认为不再区分这两个概念是一个糟糕的决定在命名方面很清楚。此外,公共点语言子集定义在一个名为 aopalliance.jar 的小 JAR 中,因为很久以前所谓的“AOP 联盟”已经定义了该语法。不过,目前占主导地位且迄今为止最强大的 AOP 语言是 AspectJ,因此实际上 AspectJ(由 Eclipse 维护)是该领域的领导者,即 IMO。
    • 当我说 Spring AOP 使用 AspectJ 语法的一个子集时,相反,它意味着 AspectJ 提供了一个超集。还有更多的切入点类型,例如call()set()get() 等,并且您可以通过建议或类型间定义来拦截连接点并将横切关注点应用于您的代码库。

    我不明白你的问题 #2。您示例中的配置类确实使用注释,因此没有第三种方式。 ;-) 但是在 Spring 中有一种古老的、非常过时的 AOP 方法,称为拦截器。它是早期 AOP 方法的遗留物,现在已经过时了,尽管它仍然可用。

    Spring AOP 和 AspectJ 都可以通过 XML 或 Spring 中的注释进行配置。 :-)

    【讨论】:

    • 很好的答案,我只在 Spring AOP 方面与 AspectJ 合作过,这个答案帮助我更多地了解它们如何协同工作。 +1
    【解决方案2】:

    不确定我是否完全理解您的问题,我想您是在问类似这样的问题:“如果我使用的是 Spring AOP,为什么我会看到对 AspectJ 的引用?”

    如果是这样,您应该知道 Spring 不是在与 AspectJ 竞争,而是利用AspectJ 实现 AOP。

    查看 Spring 文档:http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/html/aop.html

    【讨论】:

    • 我不同意,有点。 Spring 框架本身并不与 AspectJ 竞争,因为它通过配置支持自己的 Spring AOP 和成熟的 AspectJ。但是这两种 AOP 替代方案是相互竞争的,因为您可以使用 Spring AOP 做的所有事情也可以使用 AspectJ 以及更多功能来完成。所以一旦 Spring AOP 有限的特性集不够用,就需要使用 AspectJ。没有什么可以阻止您从一开始就only 使用 AspectJ,即完全忽略 Spring AOP。所以在这方面两者是竞争对手。否则我同意。 :-)
    • 我也能看到这种观点。我只是按照 Spring 文档所说的去做。当然,这可能只是 Spring 的人在外交。
    • 我同意这两个 AOP 框架在 Spring 中和平共处。 :-) 也许这就是他们的意思。
    猜你喜欢
    • 1970-01-01
    • 2012-08-20
    • 2015-06-07
    • 1970-01-01
    • 2015-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多