Spring aop源码浅析(一)
发布日期:2021-06-27 12:55:38 浏览次数:40 分类:技术文章

本文共 10438 字,大约阅读时间需要 34 分钟。

众所周知,AOP(Aspect-Oriented Programming),面向切面编程,是Spring框架三大特性之一。他是基于AOP Alliance组织发布的Java/J2EE AOP标准的一个实现。AOP Alliance通过封装Java的一些reflect(反射)相关接口和类,编写出了一系列AOP相关操作的接口。而spring-aop包则是对这些操作接口的一个具体实现。

由于一些未知原因,spring-aop的1.0版本无法下载javadoc,也无法找到当时使用的AOP Alliance源码。所以以下浅析采用的是spring-aop的5.2.12.RELEASE版本源码。

源码中包含了两部分:一部分是aopalliance组织的规范,一部分是springframework对AOP的具体实现。

这篇文章,将会对AOP规范进行浅析。

下图为aopalliance的所有类与接口,其中包括(形式主义的)aop包和对接口进行一定定义的intercept包。

aop-pic-1.png

aop包

aop包是一个对aop的宽泛定义,包括Advice接口和AspectException异常类。

Advice接口

以下为Advice的源码:

package org.aopalliance.aop;/** * Tag interface for Advice. Implementations can be any type * of advice, such as Interceptors. * * @author Rod Johnson * @version $Id: Advice.java,v 1.1 2004/03/19 17:02:16 johnsonr Exp $ */public interface Advice {
}

Advice接口是用作标记一些建议的,内部没有任何方法。

通过继承Advice接口来表明这个接口是对aop实现的一些建议。(为什么不用类继承?因为继承Advice接口的主要目的是做一些aop相关的定义,而类并不是用来做像接口一样的定义规约的,哪怕抽象类也不是)

AspectException类

依旧,以下是AspectException的源码:

package org.aopalliance.aop;/** * Superclass for all AOP infrastructure exceptions. * Unchecked, as such exceptions are fatal and end user * code shouldn't be forced to catch them. * * @author Rod Johnson * @author Bob Lee * @author Juergen Hoeller */@SuppressWarnings("serial")public class AspectException extends RuntimeException {
/** * Constructor for AspectException. * @param message the exception message */ public AspectException(String message) {
super(message); } /** * Constructor for AspectException. * @param message the exception message * @param cause the root cause, if any */ public AspectException(String message, Throwable cause) {
super(message, cause); }}

AspectException被定义为aop中所有基础异常的父类。由于AspectException是继承于RuntimeExceotion的,而RuntimeException和他的子类在Java异常中是不受约束的(unchecked)。(如果这种异常在方法或构造函数中抛出后并没有对其进行捕获处理,那你也没有必要去用throws子句将异常传达给调用方,而且哪怕你不对抛出这种异常的方法的调用代码进行异常捕获处理,他也会通过编译检测。而这种异常抛出后会直接被JVM捕获,并停止当前线程运行)所以AspectException一旦抛出,说明问题比较严重。所以在异常发生的调用代码也没有必要去强行捕获处理这个异常。

总而言之,这是一个为了做aop框架实现时能防止使用者做出违规操作而制定的异常基类。

intercept包

intercept包中包含了我们熟知的joinpoint接口(但这和aspectj中的joinpoint根本不一样),以及基于advice接口给出的interceptor相关接口规范和基于joinpoint实现的invocation相关接口规范

Joinpoint接口

以下是aopalliance里的joinpoint源码:

package org.aopalliance.intercept;import java.lang.reflect.AccessibleObject;/** * This interface represents a generic runtime joinpoint (in the AOP * terminology). * * 

A runtime joinpoint is an event that occurs on a static * joinpoint (i.e. a location in a the program). For instance, an * invocation is the runtime joinpoint on a method (static joinpoint). * The static part of a given joinpoint can be generically retrieved * using the {@link #getStaticPart()} method. * *

In the context of an interception framework, a runtime joinpoint * is then the reification of an access to an accessible object (a * method, a constructor, a field), i.e. the static part of the * joinpoint. It is passed to the interceptors that are installed on * the static joinpoint. * * @author Rod Johnson * @see Interceptor */public interface Joinpoint {

/** * Proceed to the next interceptor in the chain. *

The implementation and the semantics of this method depends * on the actual joinpoint type (see the children interfaces). * @return see the children interfaces' proceed definition * @throws Throwable if the joinpoint throws an exception */ Object proceed() throws Throwable; /** * Return the object that holds the current joinpoint's static part. *

For instance, the target object for an invocation. * @return the object (can be null if the accessible object is static) */ Object getThis(); /** * Return the static part of this joinpoint. *

The static part is an accessible object on which a chain of * interceptors are installed. */ AccessibleObject getStaticPart();}

joinpoint,是在静态的(固定的)地方,比如方法上加的一个连接点。然后就可以通过用拦截器拦截来获取当前连接点,从而对连接的方法(或别的什么东西)进行操作。那么操作的方法这里给出了三个:proceed()——跳转到拦截链中的下一个拦截器;getThis()——获取当前接入方法的静态部分(调用的对象之类),如果可获取到的对象是静态的,那么将会返回null;getStaticPart()——在有拦截链的情况下获取到getThis()获取不到的静态对象。其中,AccessibleObject是java反射中的一个对象类型,可以在反射的时候让一些本没有权限访问的对象变得能访问(通过屏蔽java的权限检查),并进行一些操作。

Interceptor接口

Interceptor接口继承于Advice接口,以下是源码:

package org.aopalliance.intercept;import org.aopalliance.aop.Advice;/** * This interface represents a generic interceptor. * * 

A generic interceptor can intercept runtime events that occur * within a base program. Those events are materialized by (reified * in) joinpoints. Runtime joinpoints can be invocations, field * access, exceptions... * *

This interface is not used directly. Use the sub-interfaces * to intercept specific events. For instance, the following class * implements some specific interceptors in order to implement a * debugger: * *

 * class DebuggingInterceptor implements MethodInterceptor, *     ConstructorInterceptor { * *   Object invoke(MethodInvocation i) throws Throwable { *     debug(i.getMethod(), i.getThis(), i.getArgs()); *     return i.proceed(); *   } * *   Object construct(ConstructorInvocation i) throws Throwable { *     debug(i.getConstructor(), i.getThis(), i.getArgs()); *     return i.proceed(); *   } * *   void debug(AccessibleObject ao, Object this, Object value) { *     ... *   } * } * 
* * @author Rod Johnson * @see Joinpoint */public interface Interceptor extends Advice {
}

显然,这个接口是一个规约描述接口。他里面没有任何方法规约,只是告诉我们Interceptor(拦截器)是一个可以通过invocations(调用)、filed access(字段访问)、exceptions(异常)等来具体化操作拦截程序运行时的事件的一个东西。而要使用拦截器的话,需要对Interceptor接口进行继承并制定拦截器的方法规约。官方也给出了构造函数与方法的拦截器接口。

ConstructorInterceptor接口

这个接口是基于Interceptor接口的构造函数拦截器接口实现,以下是源码:

package org.aopalliance.intercept;/** * Intercepts the construction of a new object. * * 

The user should implement the {@link * #construct(ConstructorInvocation)} method to modify the original * behavior. E.g. the following class implements a singleton * interceptor (allows only one unique instance for the intercepted * class): * *

 * class DebuggingInterceptor implements ConstructorInterceptor { *   Object instance=null; * *   Object construct(ConstructorInvocation i) throws Throwable { *     if(instance==null) { *       return instance=i.proceed(); *     } else { *       throw new Exception("singleton does not allow multiple instance"); *     } *   } * } * 
* * @author Rod Johnson */public interface ConstructorInterceptor extends Interceptor {
/** * Implement this method to perform extra treatments before and * after the construction of a new object. Polite implementations * would certainly like to invoke {@link Joinpoint#proceed()}. * @param invocation the construction joinpoint * @return the newly created object, which is also the result of * the call to {@link Joinpoint#proceed()}; might be replaced by * the interceptor * @throws Throwable if the interceptors or the target object * throws an exception */ Object construct(ConstructorInvocation invocation) throws Throwable;}

这个接口提供了一个construct方法,基于对方法的不同实现,可以在创建新对象的构造函数调用前后进行额外的处理。

MethodInterceptor接口

这个接口是基于Interceptor接口的方法拦截器接口实现,以下是源码:

package org.aopalliance.intercept;/** * Intercepts calls on an interface on its way to the target. These * are nested "on top" of the target. * * 

The user should implement the {@link #invoke(MethodInvocation)} * method to modify the original behavior. E.g. the following class * implements a tracing interceptor (traces all the calls on the * intercepted method(s)): * *

 * class TracingInterceptor implements MethodInterceptor { *   Object invoke(MethodInvocation i) throws Throwable { *     System.out.println("method "+i.getMethod()+" is called on "+ *                        i.getThis()+" with args "+i.getArguments()); *     Object ret=i.proceed(); *     System.out.println("method "+i.getMethod()+" returns "+ret); *     return ret; *   } * } * 
* * @author Rod Johnson */@FunctionalInterfacepublic interface MethodInterceptor extends Interceptor {
/** * Implement this method to perform extra treatments before and * after the invocation. Polite implementations would certainly * like to invoke {@link Joinpoint#proceed()}. * @param invocation the method invocation joinpoint * @return the result of the call to {@link Joinpoint#proceed()}; * might be intercepted by the interceptor * @throws Throwable if the interceptors or the target object * throws an exception */ Object invoke(MethodInvocation invocation) throws Throwable;}

这个接口提供了一个invoke方法,基于对方法的不同实现,可以在调用(接入点处的方法的调用)前后进行额外的处理。

Invocation接口

Invocation接口是一个继承于joinpoint的接口,以下是源码:

package org.aopalliance.intercept;/** * This interface represents an invocation in the program. * * 

An invocation is a joinpoint and can be intercepted by an * interceptor. * * @author Rod Johnson */public interface Invocation extends Joinpoint {

/** * Get the arguments as an array object. * It is possible to change element values within this * array to change the arguments. * @return the argument of the invocation */ Object[] getArguments();}

其实调用的话只是joinpoint的一种,他里面提供了一个getArguments方法,用于获取连接点的参数并进行修改。具体的使用,还是需要配合拦截器来使用的。因为aop就是一个通过拦截和反射来实现切入程序主体的编程方式。

ConstructorInvocation接口

这个接口是基于Invocation接口的构造函数调用接口实现,以下是源码:

package org.aopalliance.intercept;import java.lang.reflect.Constructor;/** * Description of an invocation to a constructor, given to an * interceptor upon constructor-call. * * 

A constructor invocation is a joinpoint and can be intercepted * by a constructor interceptor. * * @author Rod Johnson * @see ConstructorInterceptor */public interface ConstructorInvocation extends Invocation {

/** * Get the constructor being called. *

This method is a friendly implementation of the * {@link Joinpoint#getStaticPart()} method (same result). * @return the constructor being called */ Constructor

getConstructor();}

这个接口提供了getConstructor方法,用于在构造函数的拦截器中拦截调用的构造函数,而且这种拦截是屏蔽了java权限检查的。

MethodInvocation接口

这个接口是基于Invocation接口的方法调用接口实现,以下是源码:

package org.aopalliance.intercept;import java.lang.reflect.Method;/** * Description of an invocation to a method, given to an interceptor * upon method-call. * * 

A method invocation is a joinpoint and can be intercepted by a * method interceptor. * * @author Rod Johnson * @see MethodInterceptor */public interface MethodInvocation extends Invocation {

/** * Get the method being called. *

This method is a friendly implementation of the * {@link Joinpoint#getStaticPart()} method (same result). * @return the method being called */ Method getMethod();}

这个接口提供了getMethod方法,用于在方法的拦截器中拦截调用的方法。这种拦截也是屏蔽了java权限检查的。

以上就是对spring-aop包中的org.aopalliance包源码的浅析了,希望能给你带来帮助。若有表述不恰当的地方,欢迎指正。

转载地址:https://blog.csdn.net/weixin_43452807/article/details/117175964 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:JAVA基础特征
下一篇:浅析SOA、分布式和微服务

发表评论

最新留言

不错!
[***.144.177.141]2024年04月16日 03时58分30秒