-
静态AOP:通过修改应用程序实际的字节码来完成织入过程,从而根据需求修改和扩展代码,由于最终结果就是普通的Java字节码,因此性能较高。但是注意其缺点是,如果想作任何的修改,即使只是加入一个新的JointPoint,都必须重新编译整个程序。
-
动态AOP:织入过程是在运行时动态进行的。具体的实现有若干种,在Spring中是为所有目标对象创建代理(但不能为final类生成代理),以便Advice可以按需要被使用。虽然其性能比不上静态的AOP,但是对应用的修改不必重新编译主程序的代码。
-
建议首选Spring AOP,只在功能达不到需求的时候,或者在程序性能调优时发现性能较差时才改用AspectJ。在Spring AOP中,第一部份是AOP core,它提供了完全解耦的,纯编程式的AOP功能;第二部份则是为让我们能在程序中更简便地使用AOP而给出的一组框架服务。Spring AOP仅是所有AOP特性的一个子集,但涵盖了最常用的90%的功能。
-
Jointpoint:一个程序执行过程中的特定点。可以是方法的调用,方法执行过程本身,类的初始化,对象的实例化等。
-
Advice:在某一特定的jointpoint运行的代码。可以分为before advice, after advice等。
-
Pointcut:用来定义某一个advice应该何时执行的一组jointpoint。比如一个典型的pointcut就是对某一个类的所有方法调用的集合,通常我们会组建复杂的pointcut来控制advice什么时候执行。
-
Aspect: advice和pointcut的组合。这个组合定义了一段程序中应该包括的逻辑以及何时应该执行该逻辑。
-
Weaving:将aspect真正加入程序代码的过程。这里可以分为编译时织入和运行时织入。
-
Target: 如果一个对象的执行过程受到某个AOP操作的修改,那么它就是一个目标对象。
-
Introduction:通过引入,我们可以在一个对象中加入新的方法或字段,以改变它的结构,你可以使用引入来让任何对象实现一个特定的接口,而不需要对这个对象的类型显式地实现这个接口。
-
Spring内部有两种实现代理的方法:JDK动态代理和CGLIB代理,且CGLIB代理的性能较优。Spring AOP只支持方法级别的jointPoint。
-
接口Advisor代表一个Aspect,但这个接口不建议直接使用,而是使用其子接口,来创建各种不同的aspect。
-
ProxyFactory的addAddvice方法,这个方法内部会将提供的advice包装在一个DefaultPointCutAdvisor对象里面,它也是PointCutAdvisor的标准实现,将其配置为包含所有默认方法调用的pointcut。如果想对创建的Advisor有更多的控制,或者要向代理中添加一个introduction,那么可以自行创建Advisor并调用addAdvisor方法。同时,ProxyFactory也提供了removeAdvice,removeAdvisor等方法来删除之前加入的advisor。
-
前置advice是最有用的advice之一,它可以修改传递给目标方法的参数,也可以抛出一个异常来阻止目标方法的执行。
-
后置advice是在方法调用完成后才执行的。我们没有办法改变已经执行的方法的参数,只能读取而不能修改目标方法的执行路径或阻止目标方法的执行,更重要的是也无法修改目标方法的返回值。不过,还是可以抛出一个异常让调用者看到的是异常而不是返回值。
-
包围通知在功能上综合了前置通知和后置通知,并且可以修改方法的返回值,或者阻止方法的执行。即将目标方法的实现完全更换成新的代码。Spring的很多功能,如远程代理支持和事务管理,都是由拦截器完成的。同时,拦截器也是剖析程序运行的好办法。
-
抛出通知和后置通知一样,是在jointPoint之后运行的,不过抛出通知只在方法抛出一个异常时才执行。此外,抛出通知对程序运行本身不能做任何改变。我们可以做的只是改变抛出异常的类型,比如需要使用一个API时,它的异常设计非常糟糕,那就可以抛出通知来通知该API中所有的类,这样就能重新设计异常继承的结构,从而使之更易管理并且具备自描述性。同时,也可以用抛出通知来提供一个集中的错误日志,以此减少散布在程序各处的记录错误日志代码的数量。
要注意的是 ThrowsAdvice只是一个标志接口,里面的方法是通过反射来调用 的,其实现类必须以下面的形式来实现方法:
void afterThrowing([Method,args,target,] ThrowableSubclass);
其中前三个参数是可选的。特别地,对于抛出的每一个异常,Spring会选择签名与抛 出的异常最匹配的一个方法,如果抛出的的Advice定义了两个afterThrowing方法, 而且它们的异常类型一样,但分别有1个和4个参数,那Spring会运行含有4个参数 的afterThorwing方法。
注意,如果一个throws-advice方法本身抛出一个exception,它会覆盖原始的异常, 即改变抛出给用户的异常,改写后的一般是一个RuntimeException,因为这与任何方 法签名都是兼容的。然而,如果一个throws-advice方法抛出一个checked Exception, 那么它必须匹配目标方法抛出的异常,所以这在一定程度上与目标方法的签名是耦合 的。永远不要抛出一个非声明的与目标方法签名不兼容的checked exception。
本文详细解析了 Spring AOP 的核心概念,包括静态 AOP 和动态 AOP 的区别,关键术语如 Jointpoint、Advice 和 Pointcut 的含义,以及如何在实际项目中运用这些概念来实现日志记录、异常监控等功能。








1446

被折叠的 条评论
为什么被折叠?



