Spring AOP 源码解析系列,建议你们按顺序阅读,欢迎讨论设计模式
本章来解析最基础的ProxyFactory的源码。有人会说,如今都没人用编码的方式来写AOP了,解析它有什么用呢?我想从两点强调下:缓存
在深刻源码前,咱们应当对ProxyFactory的结构有一个概览,就如同读一本书,先浏览下目录结构,会对接下来的阅读大有裨益。架构
能够看出整个层级架构中每一个类的职责很肯定,符合了职责单一原则,在Spring中好的设计理念存在于点点滴滴里。app
在上一篇AOP的四种实现里列举了ProxyFactory建立代理的Demo。框架
public class ProxyFactoryTest { public static void main(String[] args) { // 1.建立代理工厂 ProxyFactory factory = new ProxyFactory(); // 2.设置目标对象 factory.setTarget(new ChromeBrowser()); // 3.设置代理实现接口 factory.setInterfaces(new Class[]{Browser.class}); // 4.添加前置加强 factory.addAdvice(new BrowserBeforeAdvice()); // 5.添加后置加强 factory.addAdvice(new BrowserAfterReturningAdvice()); // 6.获取代理对象 Browser browser = (Browser) factory.getProxy(); browser.visitInternet(); } }
咱们就以基于接口代理这个简单的例子来分析ProxyFactory的实现。ide
首先,基于接口的代理须要准备的元素:函数
Demo中的前5步都是处理准备工做性能
ProxyFactory的构造函数是空方法学习
setTarget时,将target对象封装成TargetSource对象,而调用的setTargetSource是AdvisedSupport的方法。ui
public void setTarget(Object target) { setTargetSource(new SingletonTargetSource(target)); } public void setTargetSource(TargetSource targetSource) { this.targetSource = (targetSource != null ? targetSource : EMPTY_TARGET_SOURCE); }
setInterfaces,赋值的也是AdvisedSupport中的interfaces属性,可是是先清空再赋值。
/** * Set the interfaces to be proxied. */ public void setInterfaces(Class<?>... interfaces) { Assert.notNull(interfaces, "Interfaces must not be null"); this.interfaces.clear(); for (Class<?> ifc : interfaces) { addInterface(ifc); } } /** * Add a new proxied interface. * [@param](https://my.oschina.net/u/2303379) intf the additional interface to proxy */ public void addInterface(Class<?> intf) { Assert.notNull(intf, "Interface must not be null"); if (!intf.isInterface()) { throw new IllegalArgumentException("[" + intf.getName() + "] is not an interface"); } if (!this.interfaces.contains(intf)) { this.interfaces.add(intf); adviceChanged(); } }
addAdvice方法则是直接调用AdvisedSupport,将Advice封装成Advisor而后添加到advisors集合中。
public void addAdvice(int pos, Advice advice) throws AopConfigException { Assert.notNull(advice, "Advice must not be null"); // 引用加强单独处理 if (advice instanceof IntroductionInfo) { // We don't need an IntroductionAdvisor for this kind of introduction: // It's fully self-describing. addAdvisor(pos, new DefaultIntroductionAdvisor(advice, (IntroductionInfo) advice)); } // DynamicIntroductionAdvice不能单独添加,必须做为IntroductionAdvisor的一部分 else if (advice instanceof DynamicIntroductionAdvice) { // We need an IntroductionAdvisor for this kind of introduction. throw new AopConfigException("DynamicIntroductionAdvice may only be added as part of IntroductionAdvisor"); } else { addAdvisor(pos, new DefaultPointcutAdvisor(advice)); } } public void addAdvisor(int pos, Advisor advisor) throws AopConfigException { if (advisor instanceof IntroductionAdvisor) { validateIntroductionAdvisor((IntroductionAdvisor) advisor); } addAdvisorInternal(pos, advisor); } private void addAdvisorInternal(int pos, Advisor advisor) throws AopConfigException { Assert.notNull(advisor, "Advisor must not be null"); if (isFrozen()) { throw new AopConfigException("Cannot add advisor: Configuration is frozen."); } if (pos > this.advisors.size()) { throw new IllegalArgumentException( "Illegal position " + pos + " in advisor list with size " + this.advisors.size()); } // 添加到advisor集合 this.advisors.add(pos, advisor); updateAdvisorArray(); adviceChanged(); }
上述的Advice都被封装成DefaultPointcutAdvisor,能够看下其构造函数
public DefaultPointcutAdvisor(Advice advice) { this(Pointcut.TRUE, advice); }
Pointcut.TRUE表示支持任何切入点。
准备工做作完了,直接经过getProxy方法获取代理对象。
public Object getProxy() { return createAopProxy().getProxy(); }
这里的createAopProxy()返回的是AopProxy类型,方法是final,而且加了锁操做。
protected final synchronized AopProxy createAopProxy() { if (!this.active) { activate(); } return getAopProxyFactory().createAopProxy(this); }
而AopProxy又是经过一个Factory工厂来建立,由于不一样的外部配置决定了返回的是JDK代理仍是CGLIB代理。这里涉及到两种设计模式,工厂模式和策略模式,来看一张类图。
能够清晰地看出,AopProxyFactory->AopProxy->Prxoy之间的结构。
先来看DefaultAopProxyFactory中建立AopProxy的方法
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { // optimize=true或proxyTargetClass=true或接口集合为空 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."); } // 目标对象Class为接口,正常使用时不会出现 if (targetClass.isInterface()) { return new JdkDynamicAopProxy(config); } return new ObjenesisCglibAopProxy(config); } else { return new JdkDynamicAopProxy(config); } }
基于外部的配置,好比设置optimize或proxyTargetClass为true,或者目标对象没有实现接口,则会返回CGLIB代理(内部有个判断targetClass是否为接口的操做,本人尝试过多种方式,除了硬编码,正常配置时都不会走),不然返回JDK代理。
对于不一样的代理方式,getProxy调用的是各自内部的实现。
JDK代理经过Proxy.newProxyInstance来实现,而且JdkDynamicAopProxy自身实现InvocationHandler代理回调接口。
[@Override](https://my.oschina.net/u/1162528) public Object getProxy() { return getProxy(ClassUtils.getDefaultClassLoader()); } [@Override](https://my.oschina.net/u/1162528) public 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); // 判断接口定义是否有equals和hashCode方法 findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); // 调用JDK建立代理方法 return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); }
方法调用时的回调方法invoke处理真正的代理请求
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 { // equals方法特殊处理 if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { // The target does not implement the equals(Object) method itself. return equals(args[0]); } // hashCode方法特殊处理 if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { // The target does not implement the hashCode() method itself. return hashCode(); } // 调用Advised接口中的方法,直接反射执行 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; // 若是exposeProxy设置为true,设置当前Proxy,它是ThreadLocal级别的 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<Object> 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. retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args); } 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. // 支持返回this的流式调用 Class<?> returnType = method.getReturnType(); if (retVal != null && retVal == target && 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 { // 释放target资源,由TargetSource子类实现 if (target != null && !targetSource.isStatic()) { // Must have come from TargetSource. targetSource.releaseTarget(target); } // 恢复currentProxy,防止被误用 if (setProxyContext) { // Restore old proxy. AopContext.setCurrentProxy(oldProxy); } } }
在整个调用过程当中,须要关注的有几点:
若是设置exposeProxy,则会设置ThreadLocal级别的currentProxy为当前执行方法的代理对象。能够在方法内使用AopContext.currentProxy()来获取代理对象。方法执行结束后,会在finally中清除currentProxy防止被误用
拦截器链的获取是一个通用方法,都是调用AdvisedSupport类,并设置了缓存以重用。
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class<?> targetClass) { MethodCacheKey cacheKey = new MethodCacheKey(method); List<Object> cached = this.methodCache.get(cacheKey); if (cached == null) { cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice( this, method, targetClass); this.methodCache.put(cacheKey, cached); } return cached; }
真正的调用在DefaultAdvisorChainFactory中,它实现了AdvisorChainFactory接口。经过遍历全部的Advisor切面,若是是PointcutAdvisor,则提取出Pointcut,而后匹配当前类和方法是否适用。另外经过AdvisorAdapterRegistry切面注册适配器将Advisor中的Advice都封装成MethodInteceptor以方便造成拦截器链。
public List<Object> 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<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length); Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass()); // 是否有引入加强 boolean hasIntroductions = hasMatchingIntroductions(config, actualClass); // 切面适配注册器,封装Advice为Advisor或MethodInterceptor AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance(); for (Advisor advisor : config.getAdvisors()) { // 切入点切面 if (advisor instanceof PointcutAdvisor) { // Add it conditionally. PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor; // Advisor是否匹配当前对象 if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) { // 获取advisor全部拦截器 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)); } } // 其余类型的Advisor直接添加 else { Interceptor[] interceptors = registry.getInterceptors(advisor); interceptorList.addAll(Arrays.asList(interceptors)); } } return interceptorList; }
3.链式调用,将全部元素封装成ReflectiveMethodInvocation,经过方法proceed进行链式调用
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); retVal = invocation.proceed();
4.Spring对于方法返回this的流式调用也作出了兼容,将返回的this替换为代理对象。
Class<?> returnType = method.getReturnType(); if (retVal != null && retVal == target && 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; }
CGLIB代理经过CglibAopProxy来实现,在Spring4.0时,封装了一个ObjenesisCglibAopProxy,它继承了CglibAopProxy。Objenesis是一个轻量级框架,能够不调用构造函数来建立对象。另外它以代理对象的className为key作了一层cache,屡次生成代理时能够提升性能。
CGLIB经过Enhancer类生成字节码对象,而后建立代理对象。来看下getProxy方法
public 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 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 UndeclaredThrowableStrategy(UndeclaredThrowableException.class)); // 返回全部回调类 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 above enhancer.setCallbackFilter(new ProxyCallbackFilter( this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset)); enhancer.setCallbackTypes(types); // Generate the proxy class and create a proxy instance. // 生成代理Class并建立代理实例 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() failed throw new AopConfigException("Unexpected AOP exception", ex); } }
getProxy方法是调用自CglibAopProxy类的,所作的无非就是建立Enhancer类,并配置目标对象,接口,回调类等,最后经过父类ObjenesisCglibAopProxy的createProxyClassAndInstance来建立或者返回缓存中的代理对象。对于CGLIB的原理这里就不细究了,毕竟本人也未深刻了解(^__^)。咱们重点关注下回调操做,经过getCallbacks方法返回的Callback集合,只用关注下DynamicAdvisedInterceptor,它便是代理实际操做的回调类,回调方法为intercept。
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { Object oldProxy = null; boolean setProxyContext = false; Class<?> targetClass = null; Object target = null; try { 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 = getTarget(); if (target != null) { targetClass = target.getClass(); } List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); Object retVal; // Check whether we only have one InvokerInterceptor: that is, // no real advice, but just reflective invocation of the target. if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) { // 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. retVal = methodProxy.invoke(target, args); } else { // We need to create a method invocation... retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed(); } retVal = processReturnType(proxy, target, method, retVal); return retVal; } finally { if (target != null) { releaseTarget(target); } if (setProxyContext) { // Restore old proxy. AopContext.setCurrentProxy(oldProxy); } } }
能够发现DynamicAdvisedInterceptor的intercept方法同JdkDynamicAopProxy的invoke方法几乎相同,最后执行链式调用的CglibMethodInvocation也是ReflectiveMethodInvocation的子类。只是对一些特殊状况选择用其余的Callback来辅助实现。
看到这里你可能以为源码仍是很复杂啊,是的,任何强大的功能的底层实现离不开对各类状况的考虑以及异常的处理等等。可是优秀的框架会把复杂的实现细节封装起来,而经过简单的架构设计向外部暴露便捷的API。所以在看源码的过程当中,不只要关注一些实现细节,更多地要关注整个架构的设计。对于Spring AOP来讲,其实就是AopProxyFactory-AopProxy-Proxy三层结构,把握住这个就把握住了骨架,剩下的就是依附于骨架的血肉。