37

我用 Spring AOP 写了一个非常简单的 Aspect。它有效,但我在理解真正发生的事情时遇到了一些问题。我不明白为什么我必须添加 aspectjweaver.jar?Spring-AOP 文档明确指出,只要我只使用 Spring-AOP,我就不需要 aspectj 编译器或编织器:

AOP 运行时仍然是纯 Spring AOP,并且不依赖于 AspectJ 编译器或编织器。

我的配置如下所示:

<aop:aspectj-autoproxy />

@Aspect
@Service
public class RemoteInvocationAspect {

    @Before("execution(* at.test.mypackage.*.*(..))")
    public void test() {
        System.out.println("test");
    }
    ...

我也尝试了 XML 配置,但没有改变任何东西。也许我可以放手,但我真的很想了解为什么要使用 aspectj-weaver?如果我不在 Maven 中添加依赖项,我会得到 java.lang.ClassNotFoundException: org.aspectj.weaver.reflect.ReflectionWorld$ReflectionWorldException

4

5 回答 5

33

我认为 Spring AOP 实现是重用了 aspectj-weaver 中的一些类。它仍然使用动态代理 - 不进行字节码修改。

春季论坛的以下评论可能会澄清。

在这种情况下,Spring 没有使用 AspectJ 编织器。它只是重用了 aspectjweaver.jar 中的一些类。

-拉姆尼瓦斯

于 2012-07-12T07:51:05.853 回答
6

您正在使用 AspectJ 风格的切入点表达式@Aspect并且@Before是 AspectJ 的一部分。检查此链接

关于AspectJ-weaver,它实际上是一个字节码编织器,它在加载时将方面编织到类中

于 2012-07-12T07:42:53.670 回答
4

我最近有一个类似的问题,如果spring不依赖于aspectj,为什么会抛出aspectj错误?

要在没有 AspectJ 依赖的情况下使用 Spring AoP,必须在 xml 中完成。注释是 AspectJ 的一部分。

此外,非常酷的表达语言仅由 AspectJ 支持。所以你必须定义明确的切入点。请参见第 6.3.2 节。声明切入点: http ://static.springsource.org/spring/docs/2.0.x/reference/aop.html部分

我仍然无法找到有关此技术的任何详细文档。

于 2013-05-20T16:07:54.567 回答
2

当您使用 AspectJ 切入点表达式语言时,您需要 aspectjtools 或 aspectjweaver 依赖项。

请参阅以下课程:

Foo.java

public interface Foo {
    void foo();
    void baz();
}

FooImpl.java

public class FooImpl implements Foo {
    @Override
    public void foo() {
        System.out.println("Foo!");
    }

    @Override
    public void baz() {
        System.out.println("Baz!");
    }
}

MethodBeforeAdviceBarImpl.java

import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;

public class MethodBeforeAdviceBarImpl implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("Bar!");
    }
}

请参阅App.java版本 - 1

import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.NameMatchMethodPointcutAdvisor;

public class App {

    public static void main(String[] args) {
        final MethodBeforeAdvice advice = new MethodBeforeAdviceBarImpl();

        final NameMatchMethodPointcutAdvisor nameMatchMethodPointcutAdvisor = new NameMatchMethodPointcutAdvisor();
        nameMatchMethodPointcutAdvisor.setMappedName("foo");
        nameMatchMethodPointcutAdvisor.setAdvice(advice);

        final ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.addAdvisor(nameMatchMethodPointcutAdvisor);

        final Foo foo = new FooImpl();
        proxyFactory.setTarget(foo);

        final Foo fooProxy = (Foo) proxyFactory.getProxy();
        fooProxy.foo();
        fooProxy.baz();
    }
}

运行此示例的输出将是:

Bar!
Foo!
Baz!

我只需要类路径中的org.springframework:spring-context.jar。现在代替 NameMatchMethodPointcutAdvisor,让我们使用AspectJExpressionPointcutAdvisor

import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor;
import org.springframework.aop.framework.ProxyFactory;

public class App {

    public static void main(String[] args) {
        final MethodBeforeAdvice advice = new MethodBeforeAdviceBarImpl();

        final AspectJExpressionPointcutAdvisor aspectJExpressionPointcutAdvisor = new AspectJExpressionPointcutAdvisor();
        aspectJExpressionPointcutAdvisor.setAdvice(advice);
        aspectJExpressionPointcutAdvisor.setExpression("execution(void biz.tugay.spashe.Foo.foo())");

        final ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.addAdvisor(aspectJExpressionPointcutAdvisor);

        final Foo foo = new FooImpl();
        proxyFactory.setTarget(foo);

        final Foo fooProxy = (Foo) proxyFactory.getProxy();
        fooProxy.foo();
        fooProxy.baz();
    }
}

同样,如果我的类路径中只有 spring-context.jar,我会得到:

An exception occured while executing the Java class. null: InvocationTargetException: org/aspectj/weaver/reflect/ReflectionWorld$ReflectionWorldException: org.aspectj.weaver.reflect.ReflectionWorld$ReflectionWorldException

当您研究AspectJExpressionPointcutAdvisor类时,您会看到它扩展了AbstractGenericPointcutAdvisor并将工作委托给AspectJExpressionPointcut的一个实例。您可以看到 AspectJExpressionPointcut 有以下导入语句:

import org.aspectj.weaver.patterns.NamePattern;
import org.aspectj.weaver.reflect.ReflectionWorld.ReflectionWorldException;
import org.aspectj.weaver.reflect.ShadowMatchImpl;
import org.aspectj.weaver.tools.ContextBasedMatcher;
import org.aspectj.weaver.tools.FuzzyBoolean;
import org.aspectj.weaver.tools.JoinPointMatch;
import org.aspectj.weaver.tools.MatchingContext;
import org.aspectj.weaver.tools.PointcutDesignatorHandler;
import org.aspectj.weaver.tools.PointcutExpression;
import org.aspectj.weaver.tools.PointcutParameter;
import org.aspectj.weaver.tools.PointcutParser;
import org.aspectj.weaver.tools.PointcutPrimitive;
import org.aspectj.weaver.tools.ShadowMatch;

您将需要在运行时类路径中的aspectjtools依赖项,以便 AspectJExpressionPointcut 可以加载它需要的类。

于 2017-11-01T20:00:14.860 回答
0

您可以浏览 spring 网站并在docs.spring.io页面上找到答案

可以使用 XML 或 Java 样式配置启用 @AspectJ 支持。在任何一种情况下,您还需要确保 AspectJ 的 aspectjweaver.jar 库位于应用程序的类路径中(版本 1.6.8 或更高版本)。该库在 AspectJ 发行版的“lib”目录中或通过 Maven 中央存储库可用。

于 2015-07-07T01:49:27.250 回答