1. 什么是spring的Aop
在进行源码解读之前,大家需要对Spring的Aop有基础的认识和理解,参考文章:Spring之AOP理解与应用-优快云博客
2. 源码解读
接下来,我们对AOP的源码进行一个解读。
2.1 动态代理
如果你已经对spring的Aop已经有了基础的认识,那么你一定知道它的底层是用动态代理实现的。作为一个java程序员,我们都知道,实现动态代理的方式有两种,一种是jdk自生提供了一种创建代理对象的动态代理机制,其特点是代理类必须实现了接口;另一种是cglib技术。那么Spring中到底用了哪一种呢?
其实spring中这两种代理技术都用到了,它把这两种动态代理的方式进行了封装,封装成的类叫做ProxyFactory,表示是创建代理对象的一个工厂。通过ProxyFactory,我们可以不用关心到底是用cglib还是jdk动态代理了,ProxyFactory会帮我们去判断,如果要代理的类实现了接口,那么ProxyFactory底层就会用jdk动态代理,如果没有实现接口,就会用cglib技术。
以下源码则是spring在生成AOP代理对象之前需要决定到底是使用JDK动态代理还是CGLIB技术:
AopProxyFactory的子类DefaultAopProxyFactory中的createAopProxy方法@Override public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { // 如果ProxyFactory的isOptimize为true,Spring认为cglib比jdk动态代理要快 // 或者isProxyTargetClass为true, // 或者被代理对象没有实现接口, // 或者只实现了SpringProxy这个接口 // 那么则利用Cglib进行动态代理,但如果被代理类是接口,或者被代理类已经是进行过JDK动态代理而生成的代理类了则只能进行JDK动态代理 // 其他情况都会进行JDK动态代理,比如被代理类实现了除SpringProxy接口之外的其他接口 // 是不是在GraalVM虚拟机上运行 if (!NativeDetector.inNativeImage() && (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."); } // targetClass是接口,直接使用Jdk动态代理 if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); } // 使用Cglib return new ObjenesisCglibAopProxy(config); } else { // 使用Jdk动态代理 return new JdkDynamicAopProxy(config); } }
2.2 代理对象创建过程
根据上述源码中,我们得知,spring会自己判断用JDK动态代理还是Cglib动态代理,接下来,我们看一下,spring如何创建一个动态代理的对象;
2.2.1 Spring中JDK动态代理创建代理对象
spring使用JDK代理创建代理对象的整体脉络:
1. 在构造JdkDynamicAopProxy对象时,会先拿到被代理对象自己所实现的接口,并且额外的增加SpringProxy、Advised、DecoratingProxy三个接口,组合成一个Class[],并赋值给
proxiedInterfaces属性。
2. 并且检查这些接口中是否定义了equals()、hashcode()方法。
3. 执行 Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this) ,得到代理对象,JdkDynamicAopProxy作为InvocationHandler,代理对象在执行某个方法时,会进入到
JdkDynamicAopProxy的**invoke()**方法中
源码分析:
spring JDK动态代理的类是:JdkDynamicAopProxy,下述源码是JdkDynamicAopProxy的构造函数:
/** * 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.getAdvisorCount() == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) { throw new AopConfigException("No advisors and no TargetSource specified"); } this.advised = config; // 设置JDK动态代理所要代理的接口 this.proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true); //判断被代理的接口中是否定义了equals()、hashCode()方法,如果程序员在接口中手动定义了这两个方法,则也会进行代理 findDefinedEqualsAndHashCodeMethods(this.proxiedInterfaces); }
接下来,我们看一下如何设置proxiedInterfaces属性的方法:AopProxyUtils中的static Class<?>[] completeProxiedInterfaces(AdvisedSupport advised, boolean decoratingProxy)
/** * Determine the complete set of interfaces to proxy for the given AOP configuration. * <p>This will always add the {@link Advised} interface unless the AdvisedSupport's * {@link AdvisedSupport#setOpaque "opaque"} flag is on. Always adds the * {@link org.springframework.aop.SpringProxy} marker interface. * @param advised the proxy config * @param decoratingProxy whether to expose the {@link DecoratingProxy} interface * @return the complete set of interfaces to proxy * @since 4.3 * @see SpringProxy * @see Advised * @see DecoratingProxy */ static Class<?>[] completeProxiedInterfaces(AdvisedSupport advised, boolean decoratingProxy) { // 被代理对象自己所实现的接口 Class<?>[] specifiedInterfaces = advised.getProxiedInterfaces(); // 如果被代理对象没有实现接口,则判断被代理类是不是接口,或者被代理类是不是已经经过JDK动态代理之后的类从而获取想对应的接口 if (specifiedInterfaces.length == 0) { // No user-specified interfaces: check whether target class is an interface. Class<?> targetClass = advised.getTargetClass(); if (targetClass != null) { if (targetClass.isInterface()) { advised.setInterfaces(targetClass); } else if (Proxy.isProxyClass(targetClass)) { advised.setInterfaces(targetClass.getInterfaces()); } specifiedInterfaces = advised.getProxiedInterfaces(); } } // 添加三个Spring内置接口:SpringProxy、Advised、DecoratingProxy List<Class<?>> proxiedInterfaces = new ArrayList<>(specifiedInterfaces.length + 3); for (Class<?> ifc : specifiedInterfaces) { // Only non-sealed interfaces are actually eligible for JDK proxying (on JDK 17) if (isSealedMethod == null || Boolean.FALSE.equals(ReflectionUtils.invokeMethod(isSealedMethod, ifc))) { proxiedInterfaces.add(ifc); } } if (!advised.isInterfaceProxied(SpringProxy.class)) { proxiedInterfaces.add(SpringProxy.class); } if (!advised.isOpaque() && !advised.isInterfaceProxied(Advised.class)) { proxiedInterfaces.add(Advised.class); } if (decoratingProxy && !advised.isInterfaceProxied(DecoratingProxy.class)) { proxiedInterfaces.add(DecoratingProxy.class); } return ClassUtils.toClassArray(proxiedInterfaces); }
紧接着我们看一下检查equals()和hashcode()的方法
/** * Finds any {@link #equals} or {@link #hashCode} method that may be defined * on the supplied set of interfaces. * @param proxiedInterfaces the interfaces to introspect */ private void findDefinedEqualsAndHashCodeMethods(Class<?>[] proxiedInterfaces) { // 判断被代理的接口中是否定义了equals()、hashCode()方法,如果程序员在接口中手动定义了这两个方法,则也会进行代理 // 否则这两个方法是不会走代理逻辑的 for (Class<?> proxiedInterface : proxiedInterfaces) { Method[] methods = proxiedInterface.getDeclaredMethods(); for (Method method : methods) { if (AopUtils.isEqualsMethod(method)) { this.equalsDefined = true; } if (AopUtils.isHashCodeMethod(method)) { this.hashCodeDefined = true; } if (this.equalsDefined && this.hashCodeDefined) { return; } } } }
接下来,我们看一下如何得到一个JDK的动态代替对象;也就是JdkDynamicAopProxy的getProxy()这个方法;
@Override public Object getProxy() { return getProxy(ClassUtils.getDefaultClassLoader()); } @Override public Object getProxy(@Nullable ClassLoader classLoader) { if (logger.isTraceEnabled()) { logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource()); } // 得到代理对象作为InvocationHandler, return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this); }
最后,我们看一下 代理对象执行某个方法时,会进入到JdkDynamicAopProxy的invoke()方法中,这个方法的具体实现
/** * Implementation of {@code InvocationHandler.invoke}. * <p>Callers will see exactly the exception thrown by the target, * unless a hook method throws an exception. */ @Override @Nullable public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object oldProxy = null; boolean setProxyContext = false; // 拿到被代理对象 TargetSource targetSource = this.advised.targetSource; 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]); } 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... // 也是直接调用Advised接口中的方法,不走代理逻辑 // 其实就是利用代理对象获取ProxyFactory中的信息 return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); } Object retVal; // 如果ProxyFactory的exposeProxy为true,则将代理对象设置到currentProxy这个ThreadLocal中去 if (this.advised.exposeProxy) { // Make invocation available if necessary. oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } // Get as late as possible to minimize the time we "own" the target, // in case it comes from a pool. // 被代理对象和代理类 target = targetSource.getTarget(); Class<?> targetClass = (target != null ? target.getClass() : null); // Get the interception chain for this method. // 代理对象在执行某个方法时,根据方法筛选出匹配的Advisor,并适配成Interceptor 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. // 如果没有Advice,则直接调用对应方法 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); } } }
2.2.2 Spring中Cglib动态代理创建代理对象
Spring中Cglib动态代理创建代理对象整体脉络:
1. 创建Enhancer对象。
2. 设置Enhancer的superClass为通过ProxyFactory.setTarget()所设置的对象的类。
3. 设置Enhancer的interfaces为通过ProxyFactory.addInterface()所添加的接口,以及
SpringProxy、Advised、DecoratingProxy接口。
4. 设置Enhancer的Callbacks为DynamicAdvisedInterceptor。
5. 最后创建一个代理对象,代理对象在执行某个方法时,会进入DynamicAdvisedInterceptor的intercept()方法中。
源码解读:
在spring中,得到一个Cglib动态代理创建的代理对象,主要通过ObjenesisCglibAopProxy
类的getProxy()方法,其具体实现在其父类CglibAopProxy中,我们看一下这个方法源码的解读:@Override public Object getProxy(@Nullable ClassLoader classLoader) { if (logger.isTraceEnabled()) { logger.trace("Creating CGLIB proxy: " + 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; // 如果被代理类本身就已经是Cglib所生成的代理类了 if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) { // 获取真正的被代理类 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的superClass为通过ProxyFactory.setTarget()所设置的对象的类 enhancer.setSuperclass(proxySuperClass); // 代理类额外要实现的接口 设置Enhancer的interfaces为通过ProxyFactory.addInterface()所添加的接口,以及 //SpringProxy、Advised、DecoratingProxy接口 enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised)); enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE); enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader)); // 获取和被代理类所匹配的Advisor 设置Enhancer的Callbacks为DynamicAdvisedInterceptor 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. return createProxyClassAndInstance(enhancer, callbacks); } catch (CodeGenerationException | IllegalArgumentException ex) { throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() + ": Common causes of this problem include using a final class or a non-visible class", ex); } catch (Throwable ex) { // TargetSource.getTarget() failed throw new AopConfigException("Unexpected AOP exception", ex); } }
接下来我们看一下 如何设置Enhancer的interfaces为通过ProxyFactory.addInterface()所添加的接口,以及SpringProxy、Advised、DecoratingProxy接口。 这个方法为AopProxyUtils类中的static Class<?>[] completeProxiedInterfaces(AdvisedSupport advised, boolean decoratingProxy) 方法,具体源码解析如下:
/** * Determine the complete set of interfaces to proxy for the given AOP configuration. * <p>This will always add the {@link Advised} interface unless the AdvisedSupport's * {@link AdvisedSupport#setOpaque "opaque"} flag is on. Always adds the * {@link org.springframework.aop.SpringProxy} marker interface. * @param advised the proxy config * @param decoratingProxy whether to expose the {@link DecoratingProxy} interface * @return the complete set of interfaces to proxy * @since 4.3 * @see SpringProxy * @see Advised * @see DecoratingProxy */ static Class<?>[] completeProxiedInterfaces(AdvisedSupport advised, boolean decoratingProxy) { // 被代理对象自己所实现的接口 Class<?>[] specifiedInterfaces = advised.getProxiedInterfaces(); // 如果被代理对象没有实现接口,则判断被代理类是不是接口,或者被代理类是不是已经经过JDK动态代理之后的类从而获取想对应的接口 if (specifiedInterfaces.length == 0) { // No user-specified interfaces: check whether target class is an interface. Class<?> targetClass = advised.getTargetClass(); if (targetClass != null) { if (targetClass.isInterface()) { advised.setInterfaces(targetClass); } else if (Proxy.isProxyClass(targetClass)) { advised.setInterfaces(targetClass.getInterfaces()); } specifiedInterfaces = advised.getProxiedInterfaces(); } } // 添加三个Spring内置接口:SpringProxy、Advised、DecoratingProxy List<Class<?>> proxiedInterfaces = new ArrayList<>(specifiedInterfaces.length + 3); for (Class<?> ifc : specifiedInterfaces) { // Only non-sealed interfaces are actually eligible for JDK proxying (on JDK 17) if (isSealedMethod == null || Boolean.FALSE.equals(ReflectionUtils.invokeMethod(isSealedMethod, ifc))) { proxiedInterfaces.add(ifc); } } if (!advised.isInterfaceProxied(SpringProxy.class)) { proxiedInterfaces.add(SpringProxy.class); } if (!advised.isOpaque() && !advised.isInterfaceProxied(Advised.class)) { proxiedInterfaces.add(Advised.class); } if (decoratingProxy && !advised.isInterfaceProxied(DecoratingProxy.class)) { proxiedInterfaces.add(DecoratingProxy.class); } return ClassUtils.toClassArray(proxiedInterfaces); }
我们再看一下如何设置Enhancer的Callbacks为DynamicAdvisedInterceptor。还是在CglibAopProxy这个类中
private Callback[] getCallbacks(Class<?> rootClass) throws Exception { // Parameters used for optimization 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 advice,执行Interceptor链 targetInterceptor, // invoke target without considering advice, if optimized 将代理对象设置到ThreadLocal中,AopContext.setCurrentProxy(proxy) 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 optimizations 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 = CollectionUtils.newHashMap(methods.length); // TODO: small memory optimization here (can skip creation for methods with no advice) for (int x = 0; x < methods.length; x++) { Method method = methods[x]; List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, rootClass); fixedCallbacks[x] = new FixedChainStaticTargetInterceptor( chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass()); this.fixedInterceptorMap.put(method, 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; }