package org.luanlouis.meditations.thinkinginspring.aop;/*** 售票服务* Created by louis on 2016/4/14.*/
public interface TicketService {//售票public void sellTicket();//问询public void inquire();//退票public void withdraw();
}
package org.luanlouis.meditations.thinkinginspring.aop;/*** RailwayStation 实现 TicketService* Created by louis on 2016/4/14.*/
public class RailwayStation implements TicketService {public void sellTicket(){System.out.println("售票............");}public void inquire() {System.out.println("问询.............");}public void withdraw() {System.out.println("退票.............");}
}
package org.luanlouis.meditations.thinkinginspring.aop;import org.springframework.aop.MethodBeforeAdvice;import java.lang.reflect.Method;/*** 执行RealSubject对象的方法之前的处理意见* Created by louis on 2016/4/14.*/
public class TicketServiceBeforeAdvice implements MethodBeforeAdvice {public void before(Method method, Object[] args, Object target) throws Throwable {System.out.println("BEFORE_ADVICE: 欢迎光临代售点....");}
}
package org.luanlouis.meditations.thinkinginspring.aop;import org.springframework.aop.AfterReturningAdvice;import java.lang.reflect.Method;/*** 返回结果时后的处理意见* Created by louis on 2016/4/14.*/
public class TicketServiceAfterReturningAdvice implements AfterReturningAdvice {@Overridepublic void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {System.out.println("AFTER_RETURNING:本次服务已结束....");}
}
package org.luanlouis.meditations.thinkinginspring.aop;import org.springframework.aop.ThrowsAdvice;import java.lang.reflect.Method;/*** 抛出异常时的处理意见* Created by louis on 2016/4/14.*/
public class TicketServiceThrowsAdvice implements ThrowsAdvice {public void afterThrowing(Exception ex){System.out.println("AFTER_THROWING....");}public void afterThrowing(Method method, Object[] args, Object target, Exception ex){System.out.println("调用过程出错啦!!!!!");}}
package org.luanlouis.meditations.thinkinginspring.aop;import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.aspectj.AspectJAroundAdvice;/**** AroundAdvice* Created by louis on 2016/4/15.*/
public class TicketServiceAroundAdvice implements MethodInterceptor {@Overridepublic Object invoke(MethodInvocation invocation) throws Throwable {System.out.println("AROUND_ADVICE:BEGIN....");Object returnValue = invocation.proceed();System.out.println("AROUND_ADVICE:END.....");return returnValue;}
}
package org.luanlouis.meditations.thinkinginspring.aop;import org.aopalliance.aop.Advice;
import org.springframework.aop.framework.ProxyFactoryBean;/*** 通过ProxyFactoryBean 手动创建 代理对象* Created by louis on 2016/4/14.*/
public class App {public static void main(String[] args) throws Exception {//1.针对不同的时期类型,提供不同的AdviceAdvice beforeAdvice = new TicketServiceBeforeAdvice();Advice afterReturningAdvice = new TicketServiceAfterReturningAdvice();Advice aroundAdvice = new TicketServiceAroundAdvice();Advice throwsAdvice = new TicketServiceThrowsAdvice();RailwayStation railwayStation = new RailwayStation();//2.创建ProxyFactoryBean,用以创建指定对象的Proxy对象ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();//3.设置Proxy的接口proxyFactoryBean.setInterfaces(TicketService.class);//4. 设置RealSubjectproxyFactoryBean.setTarget(railwayStation);//5.使用JDK基于接口实现机制的动态代理生成Proxy代理对象,如果想使用CGLIB,需要将这个flag设置成trueproxyFactoryBean.setProxyTargetClass(true);//6. 添加不同的AdviceproxyFactoryBean.addAdvice(afterReturningAdvice);proxyFactoryBean.addAdvice(aroundAdvice);proxyFactoryBean.addAdvice(throwsAdvice);proxyFactoryBean.addAdvice(beforeAdvice);proxyFactoryBean.setProxyTargetClass(false);//7通过ProxyFactoryBean生成Proxy对象TicketService ticketService = (TicketService) proxyFactoryBean.getObject();ticketService.sellTicket();}}
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {//省略若干.../** Proxy的配置信息,这里主要提供Advisor列表,并用于返回AdviceChain */private final AdvisedSupport advised;/*** Construct a new JdkDynamicAopProxy for the given AOP configuration.* @param config the AOP configuration as AdvisedSupport object* @throws AopConfigException if the config is invalid. We try to throw an informative* exception in this case, rather than let a mysterious failure happen later.*/public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {Assert.notNull(config, "AdvisedSupport must not be null");if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {throw new AopConfigException("No advisors and no TargetSource specified");}this.advised = config;}@Overridepublic Object getProxy() {return getProxy(ClassUtils.getDefaultClassLoader());}//返回代理实例对象@Overridepublic Object getProxy(ClassLoader classLoader) {if (logger.isDebugEnabled()) {logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());}Class>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);//这里的InvocationHandler设置成了当前实例对象,即对这个proxy调用的任何方法,都会调用这个类的invoke()方法//这里的invoke方法被调用,动态查找Advice列表,组成ReflectMethodInvocationreturn Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);}/*** 对当前proxy调用其上的任何方法,都将转到这个方法上* Implementation of {@code InvocationHandler.invoke}.*
Callers will see exactly the exception thrown by the target,* unless a hook method throws an exception.*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {MethodInvocation invocation;Object oldProxy = null;boolean setProxyContext = false;TargetSource targetSource = this.advised.targetSource;Class> targetClass = null;Object target = null;try {if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {// The target does not implement the equals(Object) method itself.return equals(args[0]);}if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {// The target does not implement the hashCode() method itself.return hashCode();}if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&method.getDeclaringClass().isAssignableFrom(Advised.class)) {// Service invocations on ProxyConfig with the proxy config...return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);}Object retVal;if (this.advised.exposeProxy) {// Make invocation available if necessary.oldProxy = AopContext.setCurrentProxy(proxy);setProxyContext = true;}// May be null. Get as late as possible to minimize the time we "own" the target,// in case it comes from a pool.target = targetSource.getTarget();if (target != null) {targetClass = target.getClass();}// Get the interception chain for this method.获取当前调用方法的拦截链List
4、基于Cglib子类继承方式的动态代理生成代理对象
基于Cglib子类继承方式的动态代理生成代理对象:
package org.springframework.aop.framework;
/*** CGLIB-based {@link AopProxy} implementation for the Spring AOP framework.**
Formerly named {@code Cglib2AopProxy}, as of Spring 3.2, this class depends on* Spring's own internally repackaged version of CGLIB 3..*/
@SuppressWarnings("serial")
class CglibAopProxy implements AopProxy, Serializable {// Constants for CGLIB callback array indicesprivate static final int AOP_PROXY = 0;private static final int INVOKE_TARGET = 1;private static final int NO_OVERRIDE = 2;private static final int DISPATCH_TARGET = 3;private static final int DISPATCH_ADVISED = 4;private static final int INVOKE_EQUALS = 5;private static final int INVOKE_HASHCODE = 6;/** Logger available to subclasses; static to optimize serialization */protected static final Log logger = LogFactory.getLog(CglibAopProxy.class);/** Keeps track of the Classes that we have validated for final methods */private static final Map, Boolean> validatedClasses = new WeakHashMap, Boolean>();/** The configuration used to configure this proxy */protected final AdvisedSupport advised;protected Object[] constructorArgs;protected Class>[] constructorArgTypes;/** Dispatcher used for methods on Advised */private final transient AdvisedDispatcher advisedDispatcher;private transient Map fixedInterceptorMap;private transient int fixedInterceptorOffset;/*** Create a new CglibAopProxy for the given AOP configuration.* @param config the AOP configuration as AdvisedSupport object* @throws AopConfigException if the config is invalid. We try to throw an informative* exception in this case, rather than let a mysterious failure happen later.*/public CglibAopProxy(AdvisedSupport config) throws AopConfigException {Assert.notNull(config, "AdvisedSupport must not be null");if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {throw new AopConfigException("No advisors and no TargetSource specified");}this.advised = config;this.advisedDispatcher = new AdvisedDispatcher(this.advised);}/*** Set constructor arguments to use for creating the proxy.* @param constructorArgs the constructor argument values* @param constructorArgTypes the constructor argument types*/public void setConstructorArguments(Object[] constructorArgs, Class>[] constructorArgTypes) {if (constructorArgs == null || constructorArgTypes == null) {throw new IllegalArgumentException("Both 'constructorArgs' and 'constructorArgTypes' need to be specified");}if (constructorArgs.length != constructorArgTypes.length) {throw new IllegalArgumentException("Number of 'constructorArgs' (" + constructorArgs.length +") must match number of 'constructorArgTypes' (" + constructorArgTypes.length + ")");}this.constructorArgs = constructorArgs;this.constructorArgTypes = constructorArgTypes;}@Overridepublic Object getProxy() {return getProxy(null);}@Overridepublic Object getProxy(ClassLoader classLoader) {if (logger.isDebugEnabled()) {logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());}try {Class> rootClass = this.advised.getTargetClass();Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");Class> proxySuperClass = rootClass;if (ClassUtils.isCglibProxyClass(rootClass)) {proxySuperClass = rootClass.getSuperclass();Class>[] additionalInterfaces = rootClass.getInterfaces();for (Class> additionalInterface : additionalInterfaces) {this.advised.addInterface(additionalInterface);}}// Validate the class, writing log messages as necessary.validateClassIfNecessary(proxySuperClass, classLoader);// Configure CGLIB Enhancer...Enhancer enhancer = createEnhancer();if (classLoader != null) {enhancer.setClassLoader(classLoader);if (classLoader instanceof SmartClassLoader &&((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {enhancer.setUseCache(false);}}enhancer.setSuperclass(proxySuperClass);enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));Callback[] callbacks = getCallbacks(rootClass);Class>[] types = new Class>[callbacks.length];for (int x = 0; x < types.length; x++) {types[x] = callbacks[x].getClass();}// fixedInterceptorMap only populated at this point, after getCallbacks call aboveenhancer.setCallbackFilter(new ProxyCallbackFilter(this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));enhancer.setCallbackTypes(types);// Generate the proxy class and create a proxy instance.return createProxyClassAndInstance(enhancer, callbacks);}catch (CodeGenerationException ex) {throw new AopConfigException("Could not generate CGLIB subclass of class [" +this.advised.getTargetClass() + "]: " +"Common causes of this problem include using a final class or a non-visible class",ex);}catch (IllegalArgumentException ex) {throw new AopConfigException("Could not generate CGLIB subclass of class [" +this.advised.getTargetClass() + "]: " +"Common causes of this problem include using a final class or a non-visible class",ex);}catch (Exception ex) {// TargetSource.getTarget() failedthrow new AopConfigException("Unexpected AOP exception", ex);}}protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {enhancer.setInterceptDuringConstruction(false);enhancer.setCallbacks(callbacks);return (this.constructorArgs != null ?enhancer.create(this.constructorArgTypes, this.constructorArgs) :enhancer.create());}/*** Creates the CGLIB {@link Enhancer}. Subclasses may wish to override this to return a custom* {@link Enhancer} implementation.*/protected Enhancer createEnhancer() {return new Enhancer();}private Callback[] getCallbacks(Class> rootClass) throws Exception {// Parameters used for optimisation choices...boolean exposeProxy = this.advised.isExposeProxy();boolean isFrozen = this.advised.isFrozen();boolean isStatic = this.advised.getTargetSource().isStatic();// Choose an "aop" interceptor (used for AOP calls).Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);// Choose a "straight to target" interceptor. (used for calls that are// unadvised but can return this). May be required to expose the proxy.Callback targetInterceptor;if (exposeProxy) {targetInterceptor = isStatic ?new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource());}else {targetInterceptor = isStatic ?new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :new DynamicUnadvisedInterceptor(this.advised.getTargetSource());}// Choose a "direct to target" dispatcher (used for// unadvised calls to static targets that cannot return this).Callback targetDispatcher = isStatic ?new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp();Callback[] mainCallbacks = new Callback[] {aopInterceptor, // for normal advicetargetInterceptor, // invoke target without considering advice, if optimizednew SerializableNoOp(), // no override for methods mapped to thistargetDispatcher, this.advisedDispatcher,new EqualsInterceptor(this.advised),new HashCodeInterceptor(this.advised)};Callback[] callbacks;// If the target is a static one and the advice chain is frozen,// then we can make some optimisations by sending the AOP calls// direct to the target using the fixed chain for that method.if (isStatic && isFrozen) {Method[] methods = rootClass.getMethods();Callback[] fixedCallbacks = new Callback[methods.length];this.fixedInterceptorMap = new HashMap(methods.length);// TODO: small memory optimisation here (can skip creation for methods with no advice)for (int x = 0; x < methods.length; x++) {List
/*** 包裹MethodBeforeAdvice的方法拦截器* Interceptor to wrap am {@link org.springframework.aop.MethodBeforeAdvice}.* Used internally by the AOP framework; application developers should not need* to use this class directly.** @author Rod Johnson*/
@SuppressWarnings("serial")
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {private MethodBeforeAdvice advice;/*** Create a new MethodBeforeAdviceInterceptor for the given advice.* @param advice the MethodBeforeAdvice to wrap*/public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {Assert.notNull(advice, "Advice must not be null");this.advice = advice;}@Overridepublic Object invoke(MethodInvocation mi) throws Throwable {//在调用方法之前,先执行BeforeAdvicethis.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );return mi.proceed();}}
/*** 包裹AfterReturningAdvice的方法拦截器* Interceptor to wrap am {@link org.springframework.aop.AfterReturningAdvice}.* Used internally by the AOP framework; application developers should not need* to use this class directly.** @author Rod Johnson*/
@SuppressWarnings("serial")
public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {private final AfterReturningAdvice advice;/*** Create a new AfterReturningAdviceInterceptor for the given advice.* @param advice the AfterReturningAdvice to wrap*/public AfterReturningAdviceInterceptor(AfterReturningAdvice advice) {Assert.notNull(advice, "Advice must not be null");this.advice = advice;}@Overridepublic Object invoke(MethodInvocation mi) throws Throwable {//先调用invocationObject retVal = mi.proceed();//调用成功后,调用AfterReturningAdvicethis.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());return retVal;}}
/*** Interceptor to wrap an after-throwing advice.**
The signatures on handler methods on the {@code ThrowsAdvice}* implementation method argument must be of the form: ** {@code void afterThrowing([Method, args, target], ThrowableSubclass);}**
Only the last argument is required.**
Some examples of valid methods would be:**
public void afterThrowing(Exception ex)
public void afterThrowing(RemoteException)
public void afterThrowing(Method method, Object[] args, Object target, Exception ex)
public void afterThrowing(Method method, Object[] args, Object target, ServletException ex)
**
This is a class that need not be used by users。** @ Rod * @ */ class tor , { final = ""; final Log = 。(tor。class); final ;/** on , keyed by class */ final Map, > = new , >();/*** a new tor for the given 。
* @param the that the * ( a {@link org。。aop。}* )*/ tor( ) {。(, " must not be null");this。 = ;[] = 。()。();for ( : ) {//定义的方法是方法if (。()。() &&(。()。
== 1 || 。()。 == 4) &&。class。(。()[。()。 - 1])) {// Have an 。。put(。()[。()。 - 1], );if (。()) {。debug("Found : " + );}}}if (this。。()) {throw new tion("At least one must be found in class [" + 。
() + "]");}} int t() { this。。size();}/*** the 。 Can null if not found。* @param the * @ a for the given type*/ ( ) {Class = 。();if (。()) {。trace(" to find for of type [" + 。() + "]");} = this。
public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable {protected final Object proxy;protected final Object target;protected final Method method;protected Object[] arguments;private final Class> targetClass;/*** Lazily initialized map of user-specific attributes for this invocation.*/private Map userAttributes;/*** List of MethodInterceptor and InterceptorAndDynamicMethodMatcher* that need dynamic checks.*/protected final List> interceptorsAndDynamicMethodMatchers;/*** Index from 0 of the current interceptor we're invoking.* -1 until we invoke: then the current interceptor.*/private int currentInterceptorIndex = -1;/*** Construct a new ReflectiveMethodInvocation with the given arguments.* @param proxy the proxy object that the invocation was made on* @param target the target object to invoke* @param method the method to invoke* @param arguments the arguments to invoke the method with* @param targetClass the target class, for MethodMatcher invocations* @param interceptorsAndDynamicMethodMatchers interceptors that should be applied,* along with any InterceptorAndDynamicMethodMatchers that need evaluation at runtime.* MethodMatchers included in this struct must already have been found to have matched* as far as was possibly statically. Passing an array might be about 10% faster,* but would complicate the code. And it would work only for static pointcuts.*/protected ReflectiveMethodInvocation(Object proxy, Object target, Method method, Object[] arguments,Class> targetClass, List interceptorsAndDynamicMethodMatchers) {this.proxy = proxy;//proxy对象this.target = target;//真实的realSubject对象this.targetClass = targetClass;//被代理的类类型this.method = BridgeMethodResolver.findBridgedMethod(method);//方法引用this.arguments = AopProxyUtils.adaptArgumentsIfNecessary(method, arguments);//调用参数this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers;//Advice拦截器链}@Overridepublic final Object getProxy() {return this.proxy;}@Overridepublic final Object getThis() {return this.target;}@Overridepublic final AccessibleObject getStaticPart() {return this.method;}/*** Return the method invoked on the proxied interface.* May or may not correspond with a method invoked on an underlying* implementation of that interface.*/@Overridepublic final Method getMethod() {return this.method;}@Overridepublic final Object[] getArguments() {return (this.arguments != null ? this.arguments : new Object[0]);}@Overridepublic void setArguments(Object... arguments) {this.arguments = arguments;}@Overridepublic Object proceed() throws Throwable {// 没有拦截器,则直接调用Joinpoint上的method,即直接调用MethodInvocation We start with an index of -1 and increment early.if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {return invokeJoinpoint();}// 取得第拦截器链上第N个拦截器 Object interceptorOrInterceptionAdvice =this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);//PointcutInterceptor会走这个逻辑if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {// Evaluate dynamic method matcher here: static part will already have// been evaluated and found to match.InterceptorAndDynamicMethodMatcher dm =(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;//当前拦截器是符合拦截规则,每个拦截器可以定义是否特定的类和方法名是否符合拦截规则//实际上PointCut定义的方法签名最后会转换成这个MethodMatcher,并置于拦截器中if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {//符合拦截规则,调用拦截器invoke() return dm.interceptor.invoke(this);}else {// Dynamic matching failed.// Skip this interceptor and invoke the next in the chain.// 当前方法不需要拦截器操作,则直接往前推进return proceed();}}else {// It's an interceptor, so we just invoke it: The pointcut will have// been evaluated statically before this object was constructed.//直接调用拦截器,return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);}}/*** Invoke the joinpoint using reflection.* Subclasses can override this to use custom invocation.* @return the return value of the joinpoint* @throws Throwable if invoking the joinpoint resulted in an exception*/protected Object invokeJoinpoint() throws Throwable {return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);}
public interface MethodMatcher {/*** 提供方法签名和所属的Class类型,判断是否支持 * Perform static checking whether the given method matches. If this* returns {@code false} or if the {@link #isRuntime()} method* returns {@code false}, no runtime check (i.e. no.* {@link #matches(java.lang.reflect.Method, Class, Object[])} call) will be made.* @param method the candidate method* @param targetClass the target class (may be {@code null}, in which case* the candidate class must be taken to be the method's declaring class)* @return whether or not this method matches statically*/boolean matches(Method method, Class> targetClass);/*** Is this MethodMatcher dynamic, that is, must a final call be made on the* {@link #matches(java.lang.reflect.Method, Class, Object[])} method at* runtime even if the 2-arg matches method returns {@code true}?*
Can be invoked when an AOP proxy is created, and need not be invoked* again before each method invocation,* @return whether or not a runtime match via the 3-arg* {@link #matches(java.lang.reflect.Method, Class, Object[])} method* is required if static matching passed*/boolean isRuntime();/*** Check whether there a runtime (dynamic) match for this method,* which must have matched statically.*
This method is invoked only if the 2-arg matches method returns* {@code true} for the given method and target class, and if the* {@link #isRuntime()} method returns {@code true}. Invoked* immediately before potential running of the advice, after any* advice earlier in the advice chain has run.* @param method the candidate method* @param targetClass the target class (may be {@code null}, in which case* the candidate class must be taken to be the method's declaring class)* @param args arguments to the method* @return whether there's a runtime match* @see MethodMatcher#matches(Method, Class)*/boolean matches(Method method, Class> targetClass, Object... args);/*** Canonical instance that matches all methods.*/MethodMatcher TRUE = TrueMethodMatcher.INSTANCE;}
将这个匹配器和拦截器 结合到一起,就构成了一个新的类 :
/*** Internal framework class, combining a MethodInterceptor instance* with a MethodMatcher for use as an element in the advisor chain.** @author Rod Johnson*/
class InterceptorAndDynamicMethodMatcher {final MethodInterceptor interceptor;final MethodMatcher methodMatcher;public InterceptorAndDynamicMethodMatcher(MethodInterceptor interceptor, MethodMatcher methodMatcher) {this.interceptor = interceptor;this.methodMatcher = methodMatcher;}}
我们再将上述的包含整个拦截器执行链逻辑的实现的核心代码在过一遍:
@Overridepublic Object proceed() throws Throwable {// We start with an index of -1 and increment early.if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {return invokeJoinpoint();}Object interceptorOrInterceptionAdvice =this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);//起到一定的过滤作用,如果不匹配,则直接skipif (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {// Evaluate dynamic method matcher here: static part will already have// been evaluated and found to match.InterceptorAndDynamicMethodMatcher dm =(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;//满足匹配规则,则拦截器Advice生效if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {return dm.interceptor.invoke(this);}else {// Dynamic matching failed.// Skip this interceptor and invoke the next in the chain.//拦截器尚未生效,直接skipreturn proceed();}}else {// It's an interceptor, so we just invoke it: The pointcut will have// been evaluated statically before this object was constructed.return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);}}
实战:
我们现在实现一个,表示拥有某个的。
package org.luanlouis.meditations.thinkinginspring.aop;import org.aopalliance.aop.Advice;
import org.springframework.aop.Pointcut;
import org.springframework.aop.PointcutAdvisor;/*** 实现一个PointcutAdvisor,通过提供的Pointcut,对Advice的执行进行过滤* Created by louis on 2016/4/16.*/
public class FilteredAdvisor implements PointcutAdvisor {private Pointcut pointcut;private Advice advice;public FilteredAdvisor(Pointcut pointcut, Advice advice) {this.pointcut = pointcut;this.advice = advice;}/*** Get the Pointcut that drives this advisor.*/@Overridepublic Pointcut getPointcut() {return pointcut;}@Overridepublic Advice getAdvice() {return advice;}@Overridepublic boolean isPerInstance() {return false;}
}
package org.luanlouis.meditations.thinkinginspring.aop;import org.aopalliance.aop.Advice;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.framework.ProxyFactoryBean;/*** 通过ProxyFactoryBean 手动创建 代理对象* Created by louis on 2016/4/14.*/
public class App {public static void main(String[] args) throws Exception {//1.针对不同的时期类型,提供不同的AdviceAdvice beforeAdvice = new TicketServiceBeforeAdvice();Advice afterReturningAdvice = new TicketServiceAfterReturningAdvice();Advice aroundAdvice = new TicketServiceAroundAdvice();Advice throwsAdvice = new TicketServiceThrowsAdvice();RailwayStation railwayStation = new RailwayStation();//2.创建ProxyFactoryBean,用以创建指定对象的Proxy对象ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();//3.设置Proxy的接口proxyFactoryBean.setInterfaces(TicketService.class);//4. 设置RealSubjectproxyFactoryBean.setTarget(railwayStation);//5.使用JDK基于接口实现机制的动态代理生成Proxy代理对象,如果想使用CGLIB,需要将这个flag设置成trueproxyFactoryBean.setProxyTargetClass(true);//5. 添加不同的AdviceproxyFactoryBean.addAdvice(afterReturningAdvice);proxyFactoryBean.addAdvice(aroundAdvice);proxyFactoryBean.addAdvice(throwsAdvice);//proxyFactoryBean.addAdvice(beforeAdvice);proxyFactoryBean.setProxyTargetClass(false);//手动创建一个pointcut,专门拦截sellTicket方法AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();pointcut.setExpression("execution( * sellTicket(..))");//传入创建的beforeAdvice和pointcutFilteredAdvisor sellBeforeAdvior = new FilteredAdvisor(pointcut,beforeAdvice);//添加到FactoryBean中proxyFactoryBean.addAdvisor(sellBeforeAdvior);//通过ProxyFactoryBean生成TicketService ticketService = (TicketService) proxyFactoryBean.getObject();ticketService.sellTicket();System.out.println("---------------------------");ticketService.inquire();}}