SpringAop 源码解析 (二) - 代理对象的创建以及执行过程
一、SpringAop 代理创建 以及 执行过程
在上篇文章中分析得出在使用 Aop
时,实际向 Spring
容器中注入了一个 AnnotationAwareAspectJAutoProxyCreator
动态代理 bean
生成处理器,该类有实现 BeanPostProcessor
扩展方法,并且在 postProcessAfterInitialization
进行了代理的创建,主要逻辑在 AbstractAutoProxyCreator
类下的 wrapIfNecessary
方法中,上篇文章主要分析的该方法下getAdvicesAndAdvisorsForBean
方法,主要做了对切面方法的扫描和匹配过程,并且这里拿到的结果就是所有匹配的切面方法包装类集合,本篇文章继续上篇文章的脚步,分析下后面代理对象的创建过程和执行过程。
下面是上篇文章的地址:
SpringAop 源码解析 (一) - Aspect 切面方法的查找匹配过程
二、动态代理类型的判断过程
上面文章分析到这个位置,下面继续,如果存在匹配的切面方法,则先进行标记,反之不存在也进行标记,下次再进来该 beanName
时,不存在就直接跳过了。
这里看到获取到匹配的切面方法后,通过 createProxy
方法创建了代理对象,下面看到该方法下:
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,@Nullable 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);proxyFactory.addAdvisors(advisors);proxyFactory.setTargetSource(targetSource);customizeProxyFactory(proxyFactory);proxyFactory.setFrozen(this.freezeProxy);if (advisorsPreFiltered()) {proxyFactory.setPreFiltered(true);}return proxyFactory.getProxy(getProxyClassLoader());
}
这里创建了一个代理工厂,并将切面方法、目标 bean
资源等,设置进入了该代理工厂中。
下面主要看到 proxyFactory.getProxy
又是如何创建代理对象的:
public Object getProxy(@Nullable ClassLoader classLoader) {return createAopProxy().getProxy(classLoader);
}
这里首先使用 createAopProxy
方法创建一个 AopProxy
,然后再通过AopProxy
的 getProxy
生成代理对象。
这里先看到 createAopProxy
方法下,在 ProxyCreatorSupport
类中:
protected final synchronized AopProxy createAopProxy() {if (!this.active) {activate();}// 通过 aop动态代理工厂 创建 aop动态代理return getAopProxyFactory().createAopProxy(this);
}
这里通过 AopProxyFactory
中 createAopProxy
创建一个 AopProxy
,默认情况下 AopProxyFactory
的具体实现为 DefaultAopProxyFactory
类,在ProxyCreatorSupport
类的无参构造方法中进行初始化的。
下面看到 DefaultAopProxyFactory
类中的 createAopProxy
方法中:
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {if (!IN_NATIVE_IMAGE &&(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.");}// 如果被代理对象是接口,则使用jdk动态代理if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {return new JdkDynamicAopProxy(config);}// 如果被代理对象没有实现接口,则使用 cglib 动态代理return new ObjenesisCglibAopProxy(config);}else {// 当前环境是否是原生环境,原生环境,使用 jdk动态代理return new JdkDynamicAopProxy(config);}
}
这里判断目标类是否有实现接口,如果有的话则使用 JDK
的动态代理,否则的话使用 cglib
进行代理。
下面回到上面的 getProxy
方法中,createAopProxy()
方法生成的要么是JDK
的动态代理,要么是 cglib
的动态代理,这里首先看下 JDK
动态代理的创建过程。
三、JDK 动态代理创建过程
这里先分析下 JdkDynamicAopProxy
类
可以看到实现了 InvocationHandler
接口,因此在执行代理时,会触发该类下的 invoke
方法。
再看下 JdkDynamicAopProxy
类的构造方法中做了什么事情:
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) {//如果为0就抛出异常throw new AopConfigException("No advisors and no TargetSource specified");}//注入配置this.advised = config;// 获取完整的代理接口,并进行缓存this.proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);// 判断有没有定义的equals方法和hashCode方法findDefinedEqualsAndHashCodeMethods(this.proxiedInterfaces);
}
这里先判断增强器也就是切面方法是否存在,如果不存在代理也没有意义了,接着将配置注入到 advised
属性中,最后标记出被代理类是否有定义 equals
方法和 hashCode
方法。
下面再看到 getProxy
方法,如何生成代理对象的:
public Object getProxy(@Nullable ClassLoader classLoader) {if (logger.isTraceEnabled()) {logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());}// 通过JDK 的 Proxy完成动态代理return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
}
直接通过 Proxy.newProxyInstance
创建代理实例,并且 InvocationHandler
就是自己,也就是触发执行代理时会触发该类下的 invoke
方法。
四、JDK 动态代理执行过程
JDK
动态代理执行,直接看到动态的代理的 invoke
方法中
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 {if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {// The target does not implement the equals(Object) method itself.// 如果被代理对象没有重写 equals方法,则调用本地的方法。 比较的是被代理对象return equals(args[0]);}else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {// The target does not implement the hashCode() method itself.// 如果被代理对象没有重写 hashCode 方法,则调用本地的 hashCode 方法。return hashCode();}else if (method.getDeclaringClass() == DecoratingProxy.class) {// There is only getDecoratedClass() declared -> dispatch to proxy config.// 如果实现了 DecoratingProxy的方法,则 分发给代理配置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...// 使用代理配置在ProxyConfig上调用服务return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);}// 实际方法的返回值Object retVal;// 如果需要暴露至 threadLocal,则进行暴露// 目的是在同一个类中自我方法调用的情况下// 由于执行问题 被调用的无法执行代理// 因此可以通过配置 exposeProxy 为 true,将代理方法缓存到 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.// 获取被代理类的当前方法的增强器链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.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;}//如果返回值为null,并且返回类型不是void类型,并且返回类型还被定义为基本数据类型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);}//如果暴露过proxyContextif (setProxyContext) {// Restore old proxy.// 恢复为原始的proxyAopContext.setCurrentProxy(oldProxy);}}
}
这里讲下 this.advised.exposeProxy
的作用,该值就是使用 @EnableAspectJAutoProxy
注解中的 exposeProxy
参数,如果是 true
的话,则会对当前代理对象进行缓存,目的是在同一个类中自我方法调用的情况下,如果被调用的方法带有 @Transactional
或 @Async
等注解,直接调用方法注解会失效,因为指向的是this
指针,并不是代理类,因此可以设置 exposeProxy
参数为true,将代理类缓存下来,自我调用时使用 AopContext.currentProxy()
获取到当前的代理对象,例如下面的案例:
@Component
public class TestAop {public void test(){System.out.println("test...");// 自我调用((TestAop) AopContext.currentProxy()).test2();}@Transactionalpublic void test2(){System.out.println("test2");}
}
这里的缓存其实就是使用的 ThreadLocal
进行的存储:
在继续看 invoke
方法,下面使用 this.advised.getInterceptorsAndDynamicInterceptionAdvice
生成所有匹配的切面方法的执行链,下面看到该方法中:
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable 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;
}
这里会对执行链进行缓存,这里看下缓存中不存在时,调用的 this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice
方法:
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, @Nullable Class<?> targetClass) {// This is somewhat tricky... We have to process introductions first,// but we need to preserve order in the ultimate list.// 通知器适配注册表AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();// 从动态代理配置中,获取 通知器列表Advisor[] advisors = config.getAdvisors();List<Object> interceptorList = new ArrayList<>(advisors.length);Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());Boolean hasIntroductions = null;// 遍历通知器for (Advisor advisor : advisors) {// 切点通知器if (advisor instanceof PointcutAdvisor) {// Add it conditionally.PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();// 切点通知器,需要对切面条件进行条件匹配验证boolean match;if (mm instanceof IntroductionAwareMethodMatcher) {if (hasIntroductions == null) {hasIntroductions = hasMatchingIntroductions(advisors, actualClass);}match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);}else {match = mm.matches(method, actualClass);}// 当切点匹配时,再根据切点的配置情况,加入拦截器列表if (match) {MethodInterceptor[] interceptors = registry.getInterceptors(advisor);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) {// 当切面匹配器已经在工作时,则放入 InterceptorAndDynamicMethodMatcher,运行时匹配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;
}
在该方法中,获取到之前匹配出来的切面方法,再次进行筛选匹配。
下面再回到 invoke
方法中,接着向下看如果执行链为空则直接使用 AopUtils.invokeJoinpointUsingReflection
方法触发目标方法,逻辑如下:
public static Object invokeJoinpointUsingReflection(@Nullable Object target, Method method, Object[] args)throws Throwable {// Use reflection to invoke the method.try {ReflectionUtils.makeAccessible(method);return method.invoke(target, args);}catch (InvocationTargetException ex) {// Invoked method threw a checked exception.// We must rethrow it. The client won't see the interceptor.throw ex.getTargetException();}catch (IllegalArgumentException ex) {throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" +method + "] on target [" + target + "]", ex);}catch (IllegalAccessException ex) {throw new AopInvocationException("Could not access method [" + method + "]", ex);}
}
如果执行链存在,则根据切面的配置,构造一个 ReflectiveMethodInvocation
切面方法的执行链,执行链中包含了切面方法、目标方法、目标对象等:
protected ReflectiveMethodInvocation(Object proxy, @Nullable Object target, Method method, @Nullable Object[] arguments,@Nullable Class<?> targetClass, List<Object> interceptorsAndDynamicMethodMatchers) {this.proxy = proxy;this.target = target;this.targetClass = targetClass;this.method = BridgeMethodResolver.findBridgedMethod(method);this.arguments = AopProxyUtils.adaptArgumentsIfNecessary(method, arguments);// 拦截器的动态方法匹配器this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers;
}
再向下看则调用了 invocation.proceed()
,其实是触发所有的切面增强方法,最后再触发目标方法,看到 ReflectiveMethodInvocation
类中,逻辑如下:
public Object proceed() throws Throwable {// 该方法为 jdk的AOP实现的核心// 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;//获取被代理的对象类型Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());//进行动态匹配if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {return dm.interceptor.invoke(this);}//如果动态匹配失败,递归进行proceed//不匹配就不执行当前的拦截器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);}
}
这里使用 currentInterceptorIndex
变量表示当前触发的第几个切面增强方法,首先判断的当 currentInterceptorIndex
等于interceptorsAndDynamicMethodMatchers
最后一个时,就是代表所有的切面方法都触发完了,这里的 invokeJoinpoint()
等一会再看。
先来看
((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this)
是如何触发的目标切面方法,这里可以看到实现有很多种:
这里还是以 MethodBeforeAdviceInterceptor
为例,表示 @Before
前置通知方法:
public Object invoke(MethodInvocation mi) throws Throwable {this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());// 继续触发下一个return mi.proceed();
}
这里通过 this.advice.before
触发前置通知方法后,又递归的方式触发下一个切面增强方法。这里看下 this.advice.before
怎么触发的前置通知方法:
最终触发的是 invokeAdviceMethodWithGivenArgs
方法,逻辑如下:
protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {//对参数处理Object[] actualArgs = args;if (this.aspectJAdviceMethod.getParameterCount() == 0) {actualArgs = null;}try {//下面就是通过反射来调用方法了//先让方法变得可以访问ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);// TODO AopUtils.invokeJoinpointUsingReflection//使用切面实例共产获取切面实例,然后执行建言方法return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);}catch (IllegalArgumentException ex) {throw new AopInvocationException("Mismatch on arguments to advice method [" +this.aspectJAdviceMethod + "]; pointcut expression [" +this.pointcut.getPointcutExpression() + "]", ex);}catch (InvocationTargetException ex) {throw ex.getTargetException();}
}
通过反射直接触发目标切面方法。
下面再回到 proceed()
方法中,当执行完所有的切面方法后会触发 invokeJoinpoint
方法:
这里和前面无执行链时调用逻辑一样,使用AopUtils.invokeJoinpointUsingReflection
方法触发目标方法。
五、cglib 动态代理创建过程
cglib
动态代理和 JDK
动态代理实现逻辑大致相同,这里还是先看下继承关系:
继承了 CglibAopProxy
,主要代理创建的逻辑其实都在 CglibAopProxy
中,构造方法也是调用了父类的构造方法中:
public CglibAopProxy(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;this.advisedDispatcher = new AdvisedDispatcher(this.advised);
}
同样也是将配置注入到 advised
属性中,下面主要看到 getProxy
方法 中:
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;// 如果已经被代理过,则获取原始对象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.setSuperclass(proxySuperClass);// 设置需要被代理的接口enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));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 aboveenhancer.setCallbackFilter(new ProxyCallbackFilter(this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));// 设置回调拦截器enhancer.setCallbackTypes(types);// Generate the proxy class and create a proxy instance.// 创建cglib动态代理实例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() failedthrow new AopConfigException("Unexpected AOP exception", ex);}
}
这里主要声明了 cglib
中的 Enhancer
实例,并填充代理的信息,其中创建代理对象在 createProxyClassAndInstance
方法中:
protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {enhancer.setInterceptDuringConstruction(false);enhancer.setCallbacks(callbacks);return (this.constructorArgs != null && this.constructorArgTypes != null ?enhancer.create(this.constructorArgTypes, this.constructorArgs) :enhancer.create());
}
六、cglib 动态代理执行过程
在 JDK
动态代理时,触发代理类时会触发 invoke
方法,同样在 cglib
代理中,触发代理类时,会触发 Enhancer
中 callbacks
类中的 intercept
方法,下面就从 callbacks
开始分析:
在前一步创建代理时 callbacks
就是通过 getCallbacks
方法获取的结果,下面看到该方法下:
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).// 创建 cgLib 层面的动态切面拦截器,动态代理通过它完成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;//判断是否要曝光//根据是否要曝光并且是动态代理还是静态代理去生成拦截器//这里的targetInterceptor拦截器称为目标拦截器//这个拦截器的作用实质上没有对方法进行增强,但里面的额外操作会将当前代理对象切面曝光出来//Cglib还支持静态代理咧。。。if (exposeProxy) {//如果要曝光,对应要创建exposedInterceptor//并且从创建方法可以看到,直接给了目标对象,并没有给增强器//在这里exposedInterceptor是会对代理对象进行曝光的targetInterceptor = (isStatic ?new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));}else {//如果不需要曝光,创建unadvvisedInterceptor,从名字就可以看出,是一个没有增强器的拦截器//但其实还会对返回值做一些处理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).// 创建targetDispatcher,这个跟unadvisedInterceptor的作用其实差不多// 直接执行目标对象的方法,本质上没有做其他任何其他增强操作,不过可能会对返回值做一些处理Callback targetDispatcher = (isStatic ?new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());// 将切面包装成拦截器链Callback[] mainCallbacks = new Callback[] {aopInterceptor, // for normal advicetargetInterceptor, // invoke target without considering advice, if optimizednew SerializableNoOp(), // no override for methods mapped to thistargetDispatcher, 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);//封装成FixedChainStaticTargetInterceptor存放进fixedCallBacks中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都集合起来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;
}
这里对切面增强方法生成了一个 DynamicAdvisedInterceptor
下面主要看下 DynamicAdvisedInterceptor
中的 intercept
方法:
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {Object oldProxy = null;boolean setProxyContext = false;Object target = null;TargetSource targetSource = this.advised.getTargetSource();try {// 如果需要暴露至 threadLocal,则进行暴露// 目的是在同一个类中自我方法调用的情况下// 由于执行问题 被调用的无法执行代理// 因此可以通过配置 exposeProxy 为 true,将代理方法缓存到 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);// 获取被代理类的当前方法的增强器链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.Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);retVal = methodProxy.invoke(target, argsToUse);}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 && !targetSource.isStatic()) {targetSource.releaseTarget(target);}if (setProxyContext) {// Restore old proxy.AopContext.setCurrentProxy(oldProxy);}}
}
可以看到这里实现逻辑和JDK
代理时的大致相同,如果 exposeProxy
为true
,就缓存暴露至threadLocal
中,同样使用 this.advised.getInterceptorsAndDynamicInterceptionAdvice
生成切面增强方法链。
最后 proceed()
方法同样是触发的父类的方法,和 JDK
代理执行了相同的 proceed()
方法:
public Object proceed() throws Throwable {try {return super.proceed();}catch (RuntimeException ex) {throw ex;}catch (Exception ex) {if (ReflectionUtils.declaresException(getMethod(), ex.getClass())) {throw ex;}else {throw new UndeclaredThrowableException(ex);}}
}