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