Spring AOP - 为什么我需要aspectjweaver?

时间:2012-07-12 07:24:30

标签: java spring aop aspectj spring-aop

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

  

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

5 个答案:

答案 0 :(得分:31)

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

来自春季论坛的以下comment可能会澄清。

  

在这种情况下,Spring没有使用AspectJ编织器。这很简单   重用aspectjweaver.jar中的一些类。

     

-Ramnivas

答案 1 :(得分:5)

您使用的是AspectJ样式,pointcut-expression @Aspect@Before是AspectJ的一部分。检查this link

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

答案 2 :(得分:4)

我最近有一个类似的问题Why does spring throw an aspectj error if it does not depend on aspectj?

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

此外,只有AspectJ支持真正酷的表达式语言。所以你必须定义明确的切入点。见6.3.2节。声明切入点: http://static.springsource.org/spring/docs/2.0.x/reference/aop.html部分

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

答案 3 :(得分:0)

您可以浏览spring网站,并在docs.spring.io

页面上找到答案
  

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

答案 4 :(得分:0)

使用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!

我只需要在classpath中使用 org.springframework:spring-context.jar 。现在使用 AspectJExpressionPointcutAdvisor 代替NameMatchMethodPointcutAdvisor:

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语句:

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可以加载所需的类。