在前文Spring IOC容器建立bean过程浅析已经介绍了Spring IOC建立初始化bean的大体过程。如今对Spring的AOP实现机制进行研究分析。html
名词 | 概念 |
---|---|
Advice | 通知,在链接点的处理逻辑 |
Advisor | Advisor能够简单理解为Advice+PointCut |
Interceptor | 拦截器 |
Aspect | 切面 |
AbstractAutoProxyCreator是Spring AOP实现的一个很重要的抽象类。下面是它的继承层次。
java
咱们能够注意到,它实际上是一个BeanPostProcessor。咱们须要重点关注的方法是其中的wrapIfNecessary方法,能够说这是Spring实现Bean代理的核心方法。
wrapIfNecessary在两处会被调用,一处是getEarlyBeanReference,另外一处是postProcessAfterInitialization。spring
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { if (beanName != null && this.targetSourcedBeans.contains(beanName)) { return bean; } // 判断是否不该该代理这个bean。 if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; } /* * 判断是不是一些InfrastructureClass或者是否应该跳过这个bean。 * 所谓InfrastructureClass就是指Advice/PointCut/Advisor等接口的实现类。 * shouldSkip默认实现为返回false,因为是protected方法,子类能够覆盖。 */ if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } // 获取这个bean的advice。 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); if (specificInterceptors != DO_NOT_PROXY) { this.advisedBeans.put(cacheKey, Boolean.TRUE); // 建立代理。 Object proxy = createProxy( bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } // 这个bean不须要被代理。 this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } protected Object createProxy( Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) { if (this.beanFactory instanceof ConfigurableListableBeanFactory) { AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass); } ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.copyFrom(this); 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); proxyFactory.setFrozen(this.freezeProxy); if (advisorsPreFiltered()) { proxyFactory.setPreFiltered(true); } return proxyFactory.getProxy(getProxyClassLoader()); }
从上面的createProxy方法中,咱们能够看到,最终Spring是经过ProxyFactory#getProxy的调用来获取最终的代理bean的。
下面就来看一下这其中的过程。app
public Object getProxy(ClassLoader classLoader) { return createAopProxy().getProxy(classLoader); } /** * 该方法是ProxyCreatorSupport(ProxyFactory的基类)的保护方法。 */ protected final synchronized AopProxy createAopProxy() { if (!this.active) { activate(); } return getAopProxyFactory().createAopProxy(this); }
DefaultAopProxyFactory是AopProxyFactory接口的默认实现,下面来看一下其中createAopProxy方法的实现。Spring就是在这里判断是使用JDK动态代理仍是cglib代理的。ide
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { /* * 这里是Spring判断是用JDK动态代理仍是Cglib代理的依据。 * 1. optimize开关被设置为true。此开关默认为false。 * 2. proxyTargetClass开关为true。 * 3. 没有用户代理接口。所谓用户代理接口就是指非Spring生成的代理。 * * 知足上述三点任意一点就会根据代理类自己 */ 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."); } // 若是targetClass自己是个接口或者targetClass是JDK Proxy生成的,则使用JDK动态代理。 if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); } // 不然使用Cglib代理。 return new ObjenesisCglibAopProxy(config); } else { // 使用JDK动态代理。 return new JdkDynamicAopProxy(config); } }
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, true); findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); }
能够看到本质上JdkDynamicAopProxy对于AopProxy的getProxy方法的实现本质上是调用咱们熟悉的Proxy.newProxyInstance来生成代理bean。
而JdkDynamicAopProxy自己也实现了InvocationHandler接口。下面就来看下它对InvocationHandler#invoke的实现。源码分析
@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)) { // 方法为equals且代理bean自己没有实现equals方法。 return equals(args[0]); } else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { // 方法为hashCode且代理bean自己没有实现hashCode方法。 return hashCode(); } else if (method.getDeclaringClass() == DecoratingProxy.class) { return AopProxyUtils.ultimateTargetClass(this.advised); } else if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) { return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); } Object retVal; if (this.advised.exposeProxy) { 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()) { Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse); } else { // 建立方法调用链。 invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); // 调用方法联。 retVal = invocation.proceed(); } Class<?> returnType = method.getReturnType(); // 若是返回的是this,则判断是否须要把retVal设置为代理对象。 if (retVal != null && retVal == target && returnType != Object.class && 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); } } }
Spring对于cglib建立代理,内部默认使用ObjenesisCglibAopProxy来建立代理bean,它是CglibAopProxy的子类,而且重写了createProxyClassAndInstance方法。Objenesis是一个类库,能够绕过构造器建立对象。
cglib使用Enhancer来生成代理类,生成的类实质上是被代理类的子类。更多关于Enhancer的信息,能够参考个人博文cglib之Enhancer。post
public Object getProxy(ClassLoader classLoader) { if (logger.isDebugEnabled()) { logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource()); } try { // advised其实就是建立CglibAopProxy的时候构造参数中传递的config配置。 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); } } validateClassIfNecessary(proxySuperClass, classLoader); Enhancer enhancer = createEnhancer(); if (classLoader != null) { enhancer.setClassLoader(classLoader); if (classLoader instanceof SmartClassLoader && ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) { enhancer.setUseCache(false); } } // 配置enhancer如代理接口,回调等。 enhancer.setSuperclass(proxySuperClass); enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised)); enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE); enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader)); // 这里生成callback方法的逻辑是阅读源码的重点。 Callback[] callbacks = getCallbacks(rootClass); Class<?>[] types = new Class<?>[callbacks.length]; for (int x = 0; x < types.length; x++) { types[x] = callbacks[x].getClass(); } // callbackFilter的做用主要是创建了method与callback编号的映射。 enhancer.setCallbackFilter(new ProxyCallbackFilter( this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset)); enhancer.setCallbackTypes(types); // 生成代理的class以及代理bean实例。 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) { throw new AopConfigException("Unexpected AOP exception", ex); } }
在CglibAopProxy内部定义了一组常量用于表示生成的callback索引。优化
接下来就看一下这些callback生成的具体源码实现。ui
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(); // 对于AOP方法的调用,使用DynamicAdvisedInterceptor拦截器。 Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised); /* * 不须要加强,但可能会返回this的方法: * 若是targetSource是静态的话(每次getTarget都是同一个对象),使用StaticUnadvisedExposedInterceptor * 不然使用DynamicUnadvisedExposedInterceptor。 * */ Callback targetInterceptor; if (exposeProxy) { targetInterceptor = isStatic ? new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) : new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()); } /* * 这里的分支逻辑与上面相同,只不过exposeProxy为false的状况下不会设置AopContext中的currentProxy。 */ else { targetInterceptor = isStatic ? new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) : new DynamicUnadvisedInterceptor(this.advised.getTargetSource()); } Callback targetDispatcher = isStatic ? new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp(); Callback[] mainCallbacks = new Callback[] { // AOP拦截器。 aopInterceptor, targetInterceptor, new SerializableNoOp(), targetDispatcher, this.advisedDispatcher, new EqualsInterceptor(this.advised), new HashCodeInterceptor(this.advised) }; Callback[] callbacks; /* * 若是targetSource为静态而且配置已经冻结(advice不会改变),能够封装到FixedChainStaticTargetInterceptor来拦截调用方法。 * 其实FixedChainStaticTargetInterceptor里的逻辑就至关于对固定的target每次建立CglibMethodInvocation来实现aop拦截。 */ if (isStatic && isFrozen) { Method[] methods = rootClass.getMethods(); Callback[] fixedCallbacks = new Callback[methods.length]; this.fixedInterceptorMap = new HashMap<String, Integer>(methods.length); 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); } // 把mainCallbacks和fixedCallbacks拼起来。 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; }
咱们这里主要看ProxyCallbackFilter#accept方法的源码实现。this
public int accept(Method method) { // finalize方法使用SerializableNoOp if (AopUtils.isFinalizeMethod(method)) { logger.debug("Found finalize() method - using NO_OVERRIDE"); return NO_OVERRIDE; } if (!this.advised.isOpaque() && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) { if (logger.isDebugEnabled()) { logger.debug("Method is declared on Advised interface: " + method); } return DISPATCH_ADVISED; } // equals方法使用EqualsInterceptor。 if (AopUtils.isEqualsMethod(method)) { logger.debug("Found 'equals' method: " + method); return INVOKE_EQUALS; } // hashCode方法使用HashCodeInterceptor。 if (AopUtils.isHashCodeMethod(method)) { logger.debug("Found 'hashCode' method: " + method); return INVOKE_HASHCODE; } Class<?> targetClass = this.advised.getTargetClass(); List<?> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); boolean haveAdvice = !chain.isEmpty(); boolean exposeProxy = this.advised.isExposeProxy(); boolean isStatic = this.advised.getTargetSource().isStatic(); boolean isFrozen = this.advised.isFrozen(); if (haveAdvice || !isFrozen) { // 有advice,配置没有冻结,且须要暴露proxy,使用DynamicAdvisedInterceptor。 if (exposeProxy) { if (logger.isDebugEnabled()) { logger.debug("Must expose proxy on advised method: " + method); } return AOP_PROXY; } String key = method.toString(); // 若是知足优化条件(targetSource静态且配置冻结),则尝试使用fixedInterceptor。 if (isStatic && isFrozen && this.fixedInterceptorMap.containsKey(key)) { if (logger.isDebugEnabled()) { logger.debug("Method has advice and optimisations are enabled: " + method); } // 从fixedInterceptorMap中拿到编号加上偏移量便可。 int index = this.fixedInterceptorMap.get(key); return (index + this.fixedInterceptorOffset); } else { if (logger.isDebugEnabled()) { logger.debug("Unable to apply any optimisations to advised method: " + method); } return AOP_PROXY; } } else { /* * 若是须要暴露proxy或者targetSource非静态,则使用的callback多是下面三种之一。 * StaticUnadvisedExposedInterceptor * DynamicUnadvisedExposedInterceptor * DynamicUnadvisedInterceptor */ if (exposeProxy || !isStatic) { return INVOKE_TARGET; } Class<?> returnType = method.getReturnType(); // 返回的类型与targetClass一致(有可能返回this),使用StaticUnadvisedInterceptor。 if (targetClass == returnType) { if (logger.isDebugEnabled()) { logger.debug("Method " + method + "has return type same as target type (may return this) - using INVOKE_TARGET"); } return INVOKE_TARGET; } // 返回类型为基本类型或者targetClass不兼容于返回类型(不可能返回this),使用StaticDispatcher。 else if (returnType.isPrimitive() || !returnType.isAssignableFrom(targetClass)) { if (logger.isDebugEnabled()) { logger.debug("Method " + method + " has return type that ensures this cannot be returned- using DISPATCH_TARGET"); } return DISPATCH_TARGET; } else { // 这种状况targetClass是返回类型的子类(可能返回this),使用StaticUnadvisedInterceptor。 if (logger.isDebugEnabled()) { logger.debug("Method " + method + "has return type that is assignable from the target type (may return this) - " + "using INVOKE_TARGET"); } return INVOKE_TARGET; } } }
在spring中经过cglib建立的代理中,对于须要加强的方法设置的callback为DynamicAdvisedInterceptor,它实现了cglib的MethodInterceptor。
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable { private final AdvisedSupport advised; public DynamicAdvisedInterceptor(AdvisedSupport advised) { this.advised = advised; } @Override 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; } // 拿出原始bean对象。 target = getTarget(); if (target != null) { targetClass = target.getClass(); } // 根据method和class从配置中获取加强。 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); Object retVal; // 若是没有加强而且方法为public,则直接调用。 if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) { Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); retVal = methodProxy.invoke(target, argsToUse); } else { // 建立拦截器链并调用。 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); } } } @Override public boolean equals(Object other) { return (this == other || (other instanceof DynamicAdvisedInterceptor && this.advised.equals(((DynamicAdvisedInterceptor) other).advised))); } @Override public int hashCode() { return this.advised.hashCode(); } protected Object getTarget() throws Exception { return this.advised.getTargetSource().getTarget(); } protected void releaseTarget(Object target) throws Exception { this.advised.getTargetSource().releaseTarget(target); } }
这里来看一下方法拦截器的具体实现。这个类特别重要,它是JDK动态代理和cglib代理底层都会用到的类,也就是做用在方法上的加强链的本质。
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 { // 若是不匹配的话,就递归调用proceed。 return proceed(); } } else { // 若是是一个MethodInterceptor的话则直接调用。 return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); } }
这是个很常见的问题,好比会有疑问为何一个非事务方法调用事务方法没有进入事务等等。下面经过源码来分析缘由。
经过查看源码能够看到,Spring的cglib的AOP不管方法是否有加强,本质上都是对target
进行调用。这里的target对于通常的AOP一般都是来源于
AbstractAutoProxyCreator#wrapIfNecessary中经过SingletonTargetSource包装的入参bean,而不是cglib中实际生成的proxy对象。也就是说极可能target就是一个很朴素的bean。那么进入到这样一个bean中的方法天然不会再触发cglib代理的callback拦截了。
其实能够将代理看做是一个外壳,在方法被调用的时候会被拦截进入到壳子中写好的逻辑,可是方法体自己已经脱离了外壳层,是在本体中运行的。
这个问题也是常常会困扰的问题,就是关于那些各类aop切方法,到底哪一个会先切,哪一个后切。
AbstractAutoProxyCreator#wrapIfNecessary中getAdvicesAndAdvisorsForBean用来抓取advice和advisor。
咱们以AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean的实现为例:
注意到这其中是有排序的逻辑的,以AspectJAwareAdvisorAutoProxyCreator#sortAdvisors为例能够看到用的comparator是内置的默认比较器AspectJPrecedenceComparator。
不妨再看一下AspectJPrecedenceComparator的比较策略:
能够看到会先使用内部的AnnotationAwareOrderComparator来比较,若是优先级相同,则再调用comparePrecedenceWithinAspect进行比较。
AnnotationAwareOrderComparator继承自OrderComparator, 在OrderComparator中的判断顺序逻辑是若是任一对象是PriorityOrder接口的子类型,则具备更高优先级。不然调用getOrder方法比较。
注意,上面的排序规则只是影响了各advice的调用顺序,并不表明咱们关注的aop实际逻辑的调用顺序,好比AspectJAfterAdvice#invoke也是先对methodInvocation调用proceed再处理自己的后置逻辑。