最近看了SpringAop的源码实现 大概记录一下aop的源码流程
创建一个最简单的一个测试类
package com.zcg.learn.Test;
import org.aopalliance.aop.Advice; import org.junit.Test; import org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor; import org.springframework.aop.aspectj.annotation.AspectJProxyFactory; import org.springframework.aop.framework.Advised; import org.springframework.aop.framework.ProxyFactory; import org.springframework.tests.aop.advice.CountingAfterReturningAdvice; import org.springframework.tests.aop.advice.CountingBeforeAdvice;
import com.zcg.learn.UserService; import com.zcg.learn.UserServiceImpl;
/** * SpringAop源码分析测试类 * @author zcg * 2018/3/1 * */ public class SpringAopTest {
/** * 创建代理 */ @Test public void createProxyTest() { Object target = new UserServiceImpl(); ProxyFactory pf = new ProxyFactory(target); //CountingBeforeAdvice 前置通知计数器 CountingBeforeAdvice countingBeforeAdvice = new CountingBeforeAdvice(); pf.addAdvice(countingBeforeAdvice); UserService service = (UserService) pf.getProxy(); service.addUser(); }
/** * 动态添加 移除通知 */ @Test public void createProxyTest2() { Object target = new UserServiceImpl(); ProxyFactory pf = new ProxyFactory(target); UserService service = (UserService) pf.getProxy(); Advised advised = (Advised) service; CountingBeforeAdvice countingBeforeAdvice = new CountingBeforeAdvice(); CountingAfterReturningAdvice countingAfterReturningAdvice = new CountingAfterReturningAdvice(); advised.addAdvice(countingAfterReturningAdvice); advised.addAdvice(countingBeforeAdvice); service.addUser(); advised.removeAdvice(countingAfterReturningAdvice); service.addUser(); }
@Test public void createProxyAspectJByTest() { Object target = new UserServiceImpl(); AspectJProxyFactory pf = new AspectJProxyFactory(target); AspectJExpressionPointcutAdvisor advisor = new AspectJExpressionPointcutAdvisor(); advisor.set)”); CountingBeforeAdvice counting = new CountingBeforeAdvice(); advisor.setAdvice(counting); pf.addAdvisor(advisor); UserService userService = pf.getProxy(); userService.addUser(); /** * advice 通知拦截器 * advisor 通知加切入点适配器 */
}
}
其中测试方式
@Test public void createProxyTest() { Object target = new UserServiceImpl();
ProxyFactory pf = new ProxyFactory(target); //CountingBeforeAdvice 前置通知计数器 CountingBeforeAdvice countingBeforeAdvice = new CountingBeforeAdvice(); pf.addAdvice(countingBeforeAdvice); UserService service = (UserService) pf.getProxy(); service.addUser(); }
1.target 以构造参数的形式放入在ProxyFactory中,实际上将该tartget放入在AdvisedSupport类中
2.countingBeforeAdvice 为Spring Aop自带的前置通知计数
3.1 UserService service = (UserService) pf.getProxy();从中获取代理类
ProxyFactory类中 extends ProxyCreatorSupport
/*
* 代理生成工厂 */ @SuppressWarnings(“serial”) public class ProxyFactory extends ProxyCreatorSupport {
/** * Create a new proxy according to the settings in this factory. *
Can be called repeatedly. Effect will vary if we’ve added * or removed interfaces. Can add and remove interceptors. *
Uses a default class loader: Usually, the thread context class loader * (if necessary for proxy creation). * @return the proxy object */ public Object getProxy() { return createAopProxy().getProxy(); }
}
3.2 createAopProxy()方法是父类ProxyCreatorSupport里面的方法
protected final synchronized AopProxy createAopProxy() { if (!this.active) { activate(); }
//得到Aop代理工厂和在当前代理工厂创建该代理类 return getAopProxyFactory().createAopProxy(this); }
其中getAopProxyFactory().createAopProxy(this)在DefaultAopProxyFa1ctory类中执行 具体代码如下
@SuppressWarnings(“serial”) public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
@Override public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { Class<?> targetClass = config.getTargetClass(); if (targetClass == null) { throw new AopConfigException(“TargetSource cannot determine target class: “ + “Either an interface or a target is required for proxy creation.”); }
//r如果目标类有接口或者是代理类,则走jdk的动态代理 否则走cglib的动态代理 if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); } return new ObjenesisCglibAopProxy(config); } else { return new JdkDynamicAopProxy(config); } }
/** * Determine whether the supplied {@link AdvisedSupport} has only the * {@link org.springframework.aop.SpringProxy} interface specified * (or no proxy interfaces specified at all). */ private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) { Class<?>[] ifcs = config.getProxiedInterfaces(); return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0]))); }
}
3.3 JdkDynamicAopProxy类实现了InvocationHandler 对invoke进行的重写 核心代码如下
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
@Override public 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]); } else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { // The target does not implement the hashCode() method itself. return hashCode(); } else if (method.getDeclaringClass() == DecoratingProxy.class) { // There is only getDecoratedClass() declared -> dispatch to proxy config. return AopProxyUtils.ultimateTargetClass(this.advised); } else 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 chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// Check whether we have any advice. If we don’t, we can fallback on direct // reflective invocation of the target, and avoid creating a MethodInvocation. //如果没有调用掉直接执行方式 if (chain.isEmpty()) { // We can skip creating a MethodInvocation: just invoke the target directly // Note that the final invoker must be an InvokerInterceptor so we know it does // nothing but a reflective operation on the target, and no hot swapping or fancy proxying. Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse); } else { // We need to create a method invocation…
//初始化MethodInvocation类 invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); // Proceed to the joinpoint through the interceptor chain.
执行调用链的所有方法和本身方法 retVal = invocation.proceed(); }
// Massage return value if necessary. Class<?> returnType = method.getReturnType(); if (retVal != null && retVal == target && returnType != Object.class && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { // Special case: it returned “this” and the return type of the method // is type-compatible. Note that we can’t help if the target sets // a reference to itself in another returned object. retVal = proxy; } else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) { throw new AopInvocationException( “Null return value from advice does not match primitive return type for: “ + method); } return retVal; } finally { if (target != null && !targetSource.isStatic()) { // Must have come from TargetSource. targetSource.releaseTarget(target); } if (setProxyContext) { // Restore old proxy. AopContext.setCurrentProxy(oldProxy); } } }
}
其中的 AdvisedSupport类的this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass)方法主要得到代理的所有拦截器方法
核心代码如下
public List getInterceptorsAndDynamicInterceptionAdvice(Method method, Class<?> targetClass) { MethodCacheKey cacheKey = new MethodCacheKey(method); List cached = this.methodCache.get(cacheKey); if (cached == null) { cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice( this, method, targetClass); this.methodCache.put(cacheKey, cached); } return cached; }
getInterceptorsAndDynamicInterceptionAdvice方法核心代码如下:
public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializable {
@Override public List getInterceptorsAndDynamicInterceptionAdvice( Advised config, Method method, Class<?> targetClass) {
// This is somewhat tricky… We have to process introductions first, // but we need to preserve order in the ultimate list. List interceptorList = new ArrayList(config.getAdvisors().length); Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass()); boolean hasIntroductions = hasMatchingIntroductions(config, actualClass); AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
for (Advisor advisor : config.getAdvisors()) { if (advisor instanceof PointcutAdvisor) { // Add it conditionally. PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor; if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) { MethodInterceptor[] interceptors = registry.getInterceptors(advisor); MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher(); if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) { if (mm.isRuntime()) { // Creating a new object instance in the getInterceptors() method // isn’t a problem as we normally cache created chains. for (MethodInterceptor interceptor : interceptors) { interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm)); } } else { interceptorList.addAll(Arrays.asList(interceptors)); } } } } else if (advisor instanceof IntroductionAdvisor) { IntroductionAdvisor ia = (IntroductionAdvisor) advisor; if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) { Interceptor[] interceptors = registry.getInterceptors(advisor); interceptorList.addAll(Arrays.asList(interceptors)); } } else { Interceptor[] interceptors = registry.getInterceptors(advisor); interceptorList.addAll(Arrays.asList(interceptors)); } }
return interceptorList; }
}
3.4 invocation.proceed()核心代码如下
public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable{
@Override public 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); if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { // Evaluate dynamic method matcher here: static part will already have // been evaluated and found to match.
//执行所有调用链的所有方法 InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice; 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. 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); } }
}
其中前置拦截器方法如下
@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; }
//重写invoke方法
@Override public Object invoke(MethodInvocation mi) throws Throwable { this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() ); return mi.proceed(); }
}
后置通知拦截器方法
@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; }
@Override public Object invoke(MethodInvocation mi) throws Throwable { Object retVal = mi.proceed(); this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis()); return retVal; }
}
还没有评论,来说两句吧...