代理的定义其实很是简单,就是改变原来目标对象方法调用的运行轨迹。这种改变,首先会对这些方法进行拦截,从而为这些方法提供工做空间,随后在进行回调,从而完成 AOP 切面实现的一整个逻辑。java
而建立代理是 Spring AOP 功能实现最核心的地方,通常而言 Spring AOP 动态生成代理有两种方法:JDK 和 CGLIB。下面是具体时序图:app
经过时序图的分析咱们知道她主要是由 AbstractAutoProxyCreator 类和 ProxyFactory 工厂类来完成的。下面咱们进行分析。ide
在获取了全部对应 bean 的加强器后,即可以进行代理的建立了。
函数
AbstractAutoProxyCreator.java
源码分析
protected Object createProxy( Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) { ProxyFactory proxyFactory = new ProxyFactory(); // 获取当前类中相关属性 proxyFactory.copyFrom(this); // 决定对给定的 bean 是否应该使用 targetClass 而不是他的接口代理, // 检查 proxyTargeClass 设置以及 preserveTargetClass 属性 if (!proxyFactory.isProxyTargetClass()) { if (shouldProxyTargetClass(beanClass, beanName)) { proxyFactory.setProxyTargetClass(true); } else { evaluateProxyInterfaces(beanClass, proxyFactory); } } Advisor[] advisors = buildAdvisors(beanName, specificInterceptors); for (Advisor advisor : advisors) { // 加入加强器 proxyFactory.addAdvisor(advisor); } // 设置要代理的类 proxyFactory.setTargetSource(targetSource); // 定制代理 customizeProxyFactory(proxyFactory); // 用来控制代理过程被配置以后,是否还容许修改通知。 // 缺省值为 false (即在代理被配置以后,不容许修改代理的配置) proxyFactory.setFrozen(this.freezeProxy); if (advisorsPreFiltered()) { proxyFactory.setPreFiltered(true); } return proxyFactory.getProxy(getProxyClassLoader()); }
对于代理类的建立及处理,Spring 委托给了 ProxyFactory 去处理,而在此函数中主要是对 ProxyFactory 的初始化操做,进而对真正的建立代理作准备,这些初始化操做包括6个内容:(1)获取当前类中的属性。(2)添加代理接口。(3)封装 Advisor 并加入到 ProxyFactory 中。(4)设置要代理的类。(5)固然在 Spring 中还为子类提供了定制的函数 customizeProxyFactory,子类能够在此函数中对 ProxyFactory 的进一步封装。(6)进行获取代理操做。
性能
其中,封装 Advisor 并加入到 ProxyFactory 中以及建立代理是最为繁琐的两个过程,能够经过 ProxyFactory 提供 addAdvisor 方法直接将通知器置如代理建立工厂中,可是将拦截器封装为通知器仍是须要必定逻辑的。
优化
AbstractAutoProxyCreator.javaui
protected Advisor[] buildAdvisors(String beanName, Object[] specificInterceptors) { // 解析注册的全部 interceptorName Advisor[] commonInterceptors = resolveInterceptorNames(); List<Object> allInterceptors = new ArrayList<Object>(); if (specificInterceptors != null) { // 加入拦截器 allInterceptors.addAll(Arrays.asList(specificInterceptors)); if (commonInterceptors != null) { if (this.applyCommonInterceptorsFirst) { allInterceptors.addAll(0, Arrays.asList(commonInterceptors)); } else { allInterceptors.addAll(Arrays.asList(commonInterceptors)); } } } if (logger.isDebugEnabled()) { int nrOfCommonInterceptors = (commonInterceptors != null ? commonInterceptors.length : 0); int nrOfSpecificInterceptors = (specificInterceptors != null ? specificInterceptors.length : 0); logger.debug("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors + " common interceptors and " + nrOfSpecificInterceptors + " specific interceptors"); } Advisor[] advisors = new Advisor[allInterceptors.size()]; for (int i = 0; i < allInterceptors.size(); i++) { // 拦截器进行封装转化为 Advisor advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i)); } return advisors; }
DefaultAdvisorAdapterRegistry.javathis
@Override public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException { // 若是要封装的对象自己就是 Advisor 类型的那么无需再作过多处理 if (adviceObject instanceof Advisor) { return (Advisor) adviceObject; } // 由于此封装方法只对 Advisor 与 Advice 两种类型的数据有效 if (!(adviceObject instanceof Advice)) { throw new UnknownAdviceTypeException(adviceObject); } Advice advice = (Advice) adviceObject; if (advice instanceof MethodInterceptor) { // 若是是 MethodInterceptor 类型则使用 DefaultPointcutAdvisor 封装 return new DefaultPointcutAdvisor(advice); } // 若是存在 Advisor 的适配器那么也须要进行封装 for (AdvisorAdapter adapter : this.adapters) { // Check that it is supported. if (adapter.supportsAdvice(advice)) { return new DefaultPointcutAdvisor(advice); } } throw new UnknownAdviceTypeException(advice); }
因为 Spring 中涉及过多的拦截器、通知器、加强方法等方式来对逻辑进行加强,因此很是有必要统一封装成 Advisor 来进行代理的建立,完成了加强的封装过程,那么解析最重要的一步就是代理的建立与获取了。
lua
AspectJProxyFactory.java
public <T> T getProxy(ClassLoader classLoader) { return (T) createAopProxy().getProxy(classLoader); }
咱们接着上面的例子继续进行分析。
ProxyCreatorSupport.java
protected final synchronized AopProxy createAopProxy() { if (!this.active) { activate(); } // 建立代理 return getAopProxyFactory().createAopProxy(this); }
createAopProxy 方法封装在 AopProxyFactory 接口中,经过对接口继承关系的跟踪,最终在 DefaultAopFactory中找到了其实现方法。
DefaultAopFactory.java
@Override public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { // 这里判断是使用 JDKProxy 的实现或者 CGLIBProxy 的实现 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."); } if (targetClass.isInterface()) { return new JdkDynamicAopProxy(config); } return new ObjenesisCglibAopProxy(config); } else { return new JdkDynamicAopProxy(config); } }
到此已经完成了代理建立。而源码中提到的 JDK 动态代理 和 CGLIB 字节码生成代理笔者会在随后进行介绍,这里须要注意的是if中的三个判断条件:(1)optimize:用来控制经过CGLIB建立的代理是否使用激进的优化策略。除非彻底了解AOP。不然不推荐。目前这个属性也仅仅用于 CGLIB。(2)proxyTargetClass:这个属性为 true 时,目标类自己本代理而不是目标类的接口。若是这个属性值被设为 true,CGLIB 代理将被建立,设置方式:<aop:aspectj-autoproxy proxy-target-class="true"/>。(3)hasNoUserSuppliedProxyInterfaces:是否存在代理接口。
Spring AOP 内动态生成代理有两种方法:JDK 和 CGLIB。通常状况下,若是目标对象实现了接口,默认状况下会采用 JDK 动态代理实现 AOP。若是目标对象实现了接口,能够强制使用 CGLIB 实现 AOP。若是目标对象没有实现接口,必须采用 CGLIB,Spring 会自动在 JDK动态代理和 CGLIB 之间转化。并且,JDK 动态代理只能对实现了接口的类生成代理,而不能针对类。CGLIB是针对类实现代理的,但主要是对指定的类生成一个子类,覆盖其中的方法,是继承实现,因此该类或方法最好不要声明成 final。
这里须要特别注意的是 AopProxy 接口,经过上面的代码咱们知道了,AopProxy 才是生成代理的主要位置。而前面看到的 ProxyFactory 在 AopProxy 代理对象和IOC容器配置之间仅仅起一个桥梁做用。AopProxy 代理对象能够由 JDK 或 CGLIB 来生成,而下面是他们的层次关系:
在对于 JDK 代理的使用中,JDK 动态代理的实现类 JdkDynamicAopProxy,而 JdkDynamicAopProxy 类最为核心的是 InvocationHandler 接口。而在 JdkDynamicAopProxy 类的方法里较为重要的有三个:构造函数、invoke 方法和 getProxy 方法。下面我就一个个的进行分析:
JdkDynamicAopProxy.java
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; }
从源码咱们能够看出,构造函数主要适用于传值。
JdkDynamicAopProxy.java
@Override 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); findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); }
而 getProxy 方法则是用于获取生成的代理对象的,是必不可少的方法。
JdkDynamicAopProxy.java
@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 { // equals 方法的处理 if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { return equals(args[0]); } // hash 方法的处理 if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { 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; } target = targetSource.getTarget(); if (target != null) { targetClass = target.getClass(); } // 获取当前方法的拦截器 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); if (chain.isEmpty()) { // 若是没有发现任何拦截器那么直接调入切点方法 retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args); } else { // 将拦截器封装在 ReflectiveMethodInvocation // 以便于使用期 proceed 进行连接表用拦截器 invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); // 执行拦截器链 retVal = invocation.proceed(); } // 返回结果 Class<?> returnType = method.getReturnType(); if (retVal != null && retVal == target && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { 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()) { targetSource.releaseTarget(target); } if (setProxyContext) { AopContext.setCurrentProxy(oldProxy); } } }
ReflectiveMethodInvocation.java
@Override public Object proceed() throws Throwable { // 执行完全部加强后执行切点方法 if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { return invokeJoinpoint(); } // 获取下一个要执行的拦截器 Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { // 动态匹配 InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice; if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) { return dm.interceptor.invoke(this); } else { // 不匹配则不执行拦截器 return proceed(); } } else { // 将 this 做为参数传递以保证档期实例中调用链的执行 return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); } }
经过源码咱们知道,invoke 方法是其核心逻辑实现的地方。其主要的工做就是建立一个拦截器链,而后使用 ReflectiveMethodInvocation 类对链进行封装,最后经过 proceed 方法对拦截器进行逐个调用,而 proceed 方法负责实现方法前调用以及后置调用的逻辑处理,而后将工做委托给各个加强器,在加强器内部实现具体逻辑。
CGLIB 是一个强大的高性能的代码生成包。Spring AOP 中完成 CGLIB 代理是托付给 CglibAopProxy 类来实现的,而也动态代理类似 getProxy 方法是这个类的主要入口。
CglibAopProxy.java
@Override 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); } } // 验证 Class validateClassIfNecessary(proxySuperClass, classLoader); // 建立及配置 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); // 生成代理类以及建立代理 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); } }
CGLIB 的实现最重要的就是 Enhancer。以上函数完整地阐述了建立 Spring 的 Enhancer 过程,这里值得注意的是设置拦截器链 getCallbacks 方法。
CglibAopProxy.java
private Callback[] getCallbacks(Class<?> rootClass) throws Exception { // 对于 expose-proxy 属性的处理 boolean exposeProxy = this.advised.isExposeProxy(); boolean isFrozen = this.advised.isFrozen(); boolean isStatic = this.advised.getTargetSource().isStatic(); // 将拦截器封装在 DynamicAdvisedInterceptor 中 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, // 将拦截器链加入 Callback 中 targetInterceptor, // invoke target without considering advice, if optimized new SerializableNoOp(), // no override for methods mapped to this targetDispatcher, 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<String, Integer>(methods.length); // TODO: small memory optimisation here (can skip creation for methods with no advice) for (int x = 0; x < methods.length; x++) { List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass); fixedCallbacks[x] = new FixedChainStaticTargetInterceptor( chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass()); this.fixedInterceptorMap.put(methods[x].toString(), x); } // Now copy both the callbacks from mainCallbacks // and fixedCallbacks into the callbacks array. callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length]; System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length); System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length); this.fixedInterceptorOffset = mainCallbacks.length; } else { callbacks = mainCallbacks; } return callbacks; }
至此,Spring 源码分析部分就完了,固然这仅仅是他众多实现中的一种。
——水门(2016年3月于杭州)