/** * 为true的话开启cglib代理,默认为jdk代理 * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed * to standard Java interface-based proxies. The default is {@code false}. */ booleanproxyTargetClass()defaultfalse;
/** * 是否将代理对象暴露到线程上下文中 * Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal} * for retrieval via the {@link org.springframework.aop.framework.AopContext} class. * Off by default, i.e. no guarantees that {@code AopContext} access will work. * @since 4.3.1 */ booleanexposeProxy()defaultfalse;
/** * Register, escalate, and configure the AspectJ auto proxy creator based on the value * of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing * {@code@Configuration} class. */ @Override publicvoidregisterBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry){ // 重点在这: 会注册AnnotationAwareAspectJAutoProxyCreator到BeanDefinitionMap中 // AnnotationAwareAspectJAutoProxyCreator是一个BeanPostProcessor后置处理器 // 这个方法比较简单, 可自行跟进去看一眼。 AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class); // 解析注解的属性 if (enableAspectJAutoProxy != null) { // 默认为false if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) { AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); } // 默认为false if (enableAspectJAutoProxy.getBoolean("exposeProxy")) { AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry); } } } }
@Override public Object getProxy(@Nullable ClassLoader classLoader){ if (logger.isTraceEnabled()) { logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource()); }
try { // 获取正在包装的bean的类型 Class<?> rootClass = this.advised.getTargetClass(); Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
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) { thrownew 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 thrownew AopConfigException("Unexpected AOP exception", ex); } }
@Override @Nullable 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 { 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); // 获取匹配该方法的通知列表 // 主要逻辑在DefaultAdvisorChainFactory#getInterceptorsAndDynamicInterceptionAdvice方法中 // 根据advised中的通知列表,对当前调用方法进行匹配,将匹配成功的通知转为拦截器链返回。 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... // 实例化CglibMethodInvocation后执行proceed方法 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); } } }
@Override @Nullable public Object proceed()throws Throwable { // 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); } 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. // 调用拦截器中的invoke方法,可以看到这里将this作为参数传入了,这里是一种拦截器链的典型用法 // 在我之前有篇[从myBatis Plugin看责任链模式]中有两种拦截器链的典型用法,二者的区别就是 // 有没有携带链对象,这里明显是携带链对象,从而达到拦截器链逐个执行的目的。 return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); } }