Spring AOP 源码解读(1)-AOP Alliance项目

Spring AOP 源码解读

[TOC]

AOP Alliance项目

官网

AOP Alliance 提供了AOP标准接口。org.aopalliance下面有两个包:aop、interceptor。

aop包

aop包下面只有标记接口:Advice 和 定义的运行时异常:AspectException

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 {

}

AspectException

如下,AspectException 是自定义的一个运行时异常,是所有AOP基础架构异常的超类。

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 {
//...
}

可以说,aop包总体定义了AOP的类下的‘标记’-Advice,和AOP基础异常-AspectException

interceptor包

interceptor包

由上图interceptor包下定义的都是接口,主要分为两大接口:Interceptor(拦截器)和 JoinPoint(连接点) 。

JoinPoint

package org.aopalliance.intercept;

import java.lang.reflect.AccessibleObject;

/**
 * This interface represents a generic runtime joinpoint (in the AOP
 * terminology).
 *
 * 在AOP术语中,JoinPoint 接口表示通用运行时连接点。
 *
 * <p>A runtime joinpoint is an <i>event</i> 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.
 *
 * 运行时连接点是发生在静态连接点(即程序中的位置)上的事件。例如,invocation
 (调用)就是方法(静态连接点)上的运行时连接点。可以使用getStaticPart()方法检索给定连接点的静态部分。
 
 * <p>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.
 *
 * 在拦截器框架的上下文中,运行时连接点是对可访问对象(方法,构造函数,字段,即连接点的静态部分)
 的具化。它被传递给interceptors(安装在静态连接点上的拦截器)。
 
 

 * @author Rod Johnson
 * @see Interceptor
 */
public interface Joinpoint {

	/**
	 * Proceed to the next interceptor in the chain.
	 * <p>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.
	 * <p>For instance, the target object for an invocation.
	 * @return the object (can be null if the accessible object is static)
	 *
	 * 返回保存当前连接点静态部分的对象。
	 例如,调用的目标对象。如果可访问的对象是静态的,可以为null
	 */
	Object getThis();

	/**
	 * Return the static part of this joinpoint.
	 * <p>The static part is an accessible object on which a chain of
	 * interceptors are installed.
	 *返回连接点的静态部分。静态部分是可访问对象, 对象上绑定了一系列拦截器。
	 */
	AccessibleObject getStaticPart();

}

  • 静态连接点/可访问对象:包含Field属性, Method方法 and Constructor构造函数。
  • JointPoint 指对可访问对象访问触发的事件,方法的调用,构造函数的构造,属性的getter/setter。(或者说运行时触发可访问对象件,表现在虚拟机栈上的就是栈帧)
Invocation

package org.aopalliance.intercept;

/**
 * This interface represents an invocation in the program.
 *在程序中,该接口表示调用。
 
 * <p>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();

}


  • Invocation 继承了Joinpoint,也就是一种连接点,能够被拦截。
  • 调用接口增加了一个方法,获取参数数组。
  • 其子接口又分构造器调用接口ConstructorInvocation和方法调用接口MethodInvocation
ConstructorInvocation

package org.aopalliance.intercept;

import java.lang.reflect.Constructor;

/**
 * Description of an invocation to a constuctor, given to an
 * interceptor upon constructor-call.
 *描述构造器的调用,在构造函数被调用时给予拦截器
 
 * <p>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.
     * <p>This method is a friendly implementation of the
     * {@link Joinpoint#getStaticPart()} method (same result).
     * @return the constructor being called
     获取被构造的构造器。这个方法友好地实现了Joinpoint#getStaticPart()方法(同样的结果)。
     */
    Constructor<?> getConstructor();

}

  • ConstructorInvocation 将构造器的调用具体化了,这个接口继承了Invocation,是JointPoint
  • 其方法getConstructor()能获取被调用的构造器,在调用前后扔给ConstructorInterceptor拦截。
MethodInvocation
package org.aopalliance.intercept;

import java.lang.reflect.Method;

/**
 * Description of an invocation to a method, given to an interceptor
 * upon method-call.
 *描述方法的调用,在方法被调用时给予拦截器
 
 * <p>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.
	 * <p>This method is a frienly implementation of the
	 * {@link Joinpoint#getStaticPart()} method (same result).
	 * @return the method being called
	 获取被调用的方法。改方法友好地实现了Joinpoint#getStaticPart()方法(同样的结果)。
	 */
	Method getMethod();

}
  • MethodInvocation 是针对方法的连接点。
  • 其方法getMethod()能获取被调用的方法,在调用前后扔给MethodInterceptor拦截。

Interceptor


package org.aopalliance.intercept;

import org.aopalliance.aop.Advice;

/**
 * This interface represents a generic interceptor.
 这是通用拦截器接口。
 *
 * <p>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... 
 *通用拦截器能够拦截程序中正在运行的事件。这些事件被具体化为连接点。
 运行时连接点能够被调用,字段访问限制,异常捕捉等等。
 
 * <p>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:
 *这个接口并不是直接使用,而是用子接口去拦截特定的事件。
 例如,下面类中为了完成调试而实现了一些特定的拦截器。
 
 * <pre class=code>
 * class DebuggingInterceptor implements MethodInterceptor, 
 *     ConstructorInterceptor, FieldInterceptor {
 *
 *   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();
 *   }
 * 
 *   Object get(FieldAccess fa) throws Throwable {
 *     debug(fa.getField(), fa.getThis(), null);
 *     return fa.proceed();
 *   }
 *
 *   Object set(FieldAccess fa) throws Throwable {
 *     debug(fa.getField(), fa.getThis(), fa.getValueToSet());
 *     return fa.proceed();
 *   }
 *
 *   void debug(AccessibleObject ao, Object this, Object value) {
 *     ...
 *   }
 * }
 * </pre>
 *
 * @author Rod Johnson
 * @see Joinpoint
 */
public interface Interceptor extends Advice {

}


  • Interceptor:拦截器顾名思义,就是能够拦截连接点的接口。
  • 这是一个继承了Advice的接口,同样无属性无方法,具体的拦截器需要其子接口完成。
ConstructorInterceptor

package org.aopalliance.intercept;

/**
 * Intercepts the construction of a new object.
 拦截new对象的构造器。
 *
 * <p>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):
 *用户实现这个方法去改变原来的行为。例如,下面类中实现了一个单例拦截器(被拦截的类只允许唯一一个实例)
 
 * <pre class=code>
 * 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");
 *     }
 *   }
 * }
 * </pre>
 *
 * @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
	在构建一个的新对象前后, 通过实现这个方法来做额外的处理。规范的做法肯定会调用Joinpoint#proceed()方法
	参数为 调用构造器的连接点
	返回 新建的对象,可能是唤起Joinpoint#proceed()的结果,可能被拦截器替换后的结果。
	拦截器或者目标对象会抛出Throwable异常
	 */
	Object construct(ConstructorInvocation invocation) throws Throwable;

}
  • ConstructorInterceptor入参是ConstructorInvocation,拦截构造器的调用,返回的是新建的对象。
MethodInterceptor
package org.aopalliance.intercept;

/**
 * Intercepts calls on an interface on its way to the target. These
 * are nested "on top" of the target.
 *拦截器在到达目标的路上调用接口。 这些拦截器被嵌套在目标的“顶部”上。
 
 * <p>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)):
 *用户需要实现#invoke(MethodInvocation)方法去修改原来的行为。例如下面类中实现了拦截器的跟踪(跟踪被拦截的方法上调用的所有拦截器)
 
 
 * <pre class=code>
 * 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;
 *   }
 * }
 * </pre>
 *
 * @author Rod Johnson
 */
public 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
	 在调用前后, 通过实现这个方法来做额外的处理。规范的做法肯定会调用Joinpoint#proceed()方法
	 参数为 调用方法的连接点
	 返回 Joinpoint#proceed()的结果,可能被拦截器替换后的结果。
	 拦截器或者目标对象会抛出Throwable异常
	 */
	Object invoke(MethodInvocation invocation) throws Throwable;

}
  • MethodInterceptor入参是MethodInvocation,拦截方法的调用,返回的是Joinpoint#proceed()方法执行后的结果。

总结

全文其实重点在设计和注释上面。 Rod Johnson大神注释写得很明白了。(英译中较渣) 现自己总结如下:

  • AOP Alliance 包下除了AspectException异常类外,其他全为通用接口。也正如该项目介绍的一样,提供标准统一的接口来处理面向切面编程(Aspect-Oriented Programming -AOP)的问题。

  • 其接口主要分两种类型: JoinPointAdvice(也可说InterceptorAdvice只是个标记接口)。

    • JoinPoint 为连接点,确切是运行时连接点。是对可访问对象(Filed、Method、Constructor)的调用事件,在虚拟机栈上表现为栈帧,换句话就是方法的调用,构造器的构造,字段的访问这些动作。
    • JoinPoint 子接口为InvocationInvocation本身具有获取参数数组的getArguments()方法,并且扩展出两个子接口,针对构造器的ConstructorInvocation和针对方法的MethodInvocation
  • Interceptor 即为拦截器, Advice的子接口。Interceptor亦是无属性无方法的接口,只作为定义,因而扩展出子接口ConstructorInterceptorMethodInterceptor

  • 拦截器是根据传入的连接点进行拦截,且是须一一对应(构造器拦截器拦截构造器的调用,方法拦截器拦截方法的调用),执行需要添加的处理。

  • 拦截器可以有多个,都处在target的头部,通过Joinpoint#proceed()方法一个个执行。

综上,aop原理即为将连接点JoinPoint传给对应的拦截器Interceptor拦截,并且可以在拦截前后做出额外的‘处理’。AOP不会对原来的代码进行更改,而是通过拦截的方式,在执行前后插入其他的处理,运行结果可能被改变,以达到想要的结果。

此外,再补一下java.lang.reflect包

转载于:https://my.oschina.net/u/2500836/blog/1536097

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值