之前讲过 Spring 中的自定义注解,如果声明了自定义的注解,那么就一定会在程序中的某个地方注册了对应的解析器。我们搜索整个代码,尝试找到注册的地方,全局搜索后我们发现了在 AopNamespaceHandler 中对应着这样一段函数。中间我们看到了 aspectj-autoproxy
1 2 3 4 5 6 7 8 9 10
@Override publicvoidinit() { // In 2.0 XSD as well as in 2.1 XSD. registerBeanDefinitionParser("config", newConfigBeanDefinitionParser()); registerBeanDefinitionParser("aspectj-autoproxy", newAspectJAutoProxyBeanDefinitionParser()); registerBeanDefinitionDecorator("scoped-proxy", newScopedProxyBeanDefinitionDecorator());
// Only in 2.0 XSD: moved to context namespace as of 2.1 registerBeanDefinitionParser("spring-configured", newSpringConfiguredBeanDefinitionParser()); }
// Create proxy here if we have a custom TargetSource. // Suppresses unnecessary default instantiation of the target bean: // The TargetSource will handle target instances in a custom fashion. if (beanName != null) { TargetSourcetargetSource= getCustomTargetSource(beanClass, beanName); if (targetSource != null) { this.targetSourcedBeans.add(beanName); // 如果存在增强方法则创建代理 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource); // 创建代理 Objectproxy= createProxy(beanClass, beanName, specificInterceptors, targetSource); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } }
returnnull; }
大致主流程氛围三步(判断条件走完之后):
获取需要增强的 targetSource
获取增强器
根据需要增强的 targetSource 和增强器创建代理
获取 targetSource
这部分代码与书上不符,属于多出来的步骤
这里顺便贴出 TargetSource 的说明
1 2 3 4 5 6 7 8 9 10 11 12
/** * A {@code TargetSource} is used to obtain the current "target" of * an AOP invocation, which will be invoked via reflection if no around * advice chooses to end the interceptor chain itself. * * <p>If a {@code TargetSource} is "static", it will always return * the same target, allowing optimizations in the AOP framework. Dynamic * target sources can support pooling, hot swapping, etc. * * <p>Application developers don't usually need to work with * {@code TargetSources} directly: this is an AOP framework interface. */
/** * Create a target source for bean instances. Uses any TargetSourceCreators if set. * Returns {@code null} if no custom TargetSource should be used. * <p>This implementation uses the "customTargetSourceCreators" property. * Subclasses can override this method to use a different mechanism. * @param beanClass the class of the bean to create a TargetSource for * @param beanName the name of the bean * @return a TargetSource for this bean * @see #setCustomTargetSourceCreators */ protected TargetSource getCustomTargetSource(Class<?> beanClass, String beanName) { // We can't create fancy target sources for directly registered singletons. if (this.customTargetSourceCreators != null && this.beanFactory != null && this.beanFactory.containsBean(beanName)) { for (TargetSourceCreator tsc : this.customTargetSourceCreators) { TargetSourcets= tsc.getTargetSource(beanClass, beanName); if (ts != null) { // Found a matching TargetSource. if (logger.isDebugEnabled()) { logger.debug("TargetSourceCreator [" + tsc + " found custom TargetSource for bean with name '" + beanName + "'"); } return ts; } } }
@Override protected List<Advisor> findCandidateAdvisors() { // Add all the Spring advisors found according to superclass rules. // 当使用注解方式配置 AOP 的时候并不是丢弃了对 XML 配置的支持 // 在这里调用父类方法加载配置文件中的 AOP 声明 List<Advisor> advisors = super.findCandidateAdvisors(); // Build Advisors for all AspectJ aspects in the bean factory. advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors()); return advisors; }
/** * Look for AspectJ-annotated aspect beans in the current bean factory, * and return to a list of Spring AOP Advisors representing them. * <p>Creates a Spring Advisor for each AspectJ advice method. * @return the list of {@link org.springframework.aop.Advisor} beans * @see #isEligibleBean */ public List<Advisor> buildAspectJAdvisors() { List<String> aspectNames = this.aspectBeanNames;
if (aspectNames == null) { synchronized (this) { aspectNames = this.aspectBeanNames; if (aspectNames == null) { List<Advisor> advisors = newLinkedList<Advisor>(); aspectNames = newLinkedList<String>(); // 获取所有 beanName String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.beanFactory, Object.class, true, false); // 循环所有的 beanName 找出对应的增强方法 for (String beanName : beanNames) { // 不合法的 bean 则略过,由子类定义规则,默认返回 true if (!isEligibleBean(beanName)) { continue; } // We must be careful not to instantiate beans eagerly as in this case they // would be cached by the Spring container but would not have been weaved. // 获取对应的 bean 的类型 Class<?> beanType = this.beanFactory.getType(beanName); if (beanType == null) { continue; } // 如果存在 Aspect 注解 if (this.advisorFactory.isAspect(beanType)) { aspectNames.add(beanName); AspectMetadataamd=newAspectMetadata(beanType, beanName); if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) { MetadataAwareAspectInstanceFactoryfactory= newBeanFactoryAspectInstanceFactory(this.beanFactory, beanName); // 解析标记 AspectJ 注解中的增强方法 List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory); if (this.beanFactory.isSingleton(beanName)) { this.advisorsCache.put(beanName, classAdvisors); } else { this.aspectFactoryCache.put(beanName, factory); } advisors.addAll(classAdvisors); } else { // Per target or per this. if (this.beanFactory.isSingleton(beanName)) { thrownewIllegalArgumentException("Bean with name '" + beanName + "' is a singleton, but aspect instantiation model is not singleton"); } MetadataAwareAspectInstanceFactoryfactory= newPrototypeAspectInstanceFactory(this.beanFactory, beanName); this.aspectFactoryCache.put(beanName, factory); advisors.addAll(this.advisorFactory.getAdvisors(factory)); } } } this.aspectBeanNames = aspectNames; return advisors; } } }
// We need to wrap the MetadataAwareAspectInstanceFactory with a decorator // so that it will only instantiate once. MetadataAwareAspectInstanceFactorylazySingletonAspectInstanceFactory= newLazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
// If it's a per target aspect, emit the dummy instantiating aspect. if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) { // 如果寻找的增强器不为空而且又配置了增强延迟初始化那么需要在首位加入同步实例化增强器 AdvisorinstantiationAdvisor=newSyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory); advisors.add(0, instantiationAdvisor); }
// Find introduction fields. // 获取 DeclareParents 注解 for (Field field : aspectClass.getDeclaredFields()) { Advisoradvisor= getDeclareParentsAdvisor(field); if (advisor != null) { advisors.add(advisor); } }
if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) { // Static part of the pointcut is a lazy type. PointcutpreInstantiationPointcut= Pointcuts.union( aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
// Make it dynamic: must mutate from pre-instantiation to post-instantiation state. // If it's not a dynamic pointcut, it may be optimized out // by the Spring AOP infrastructure after the first evaluation. this.pointcut = newPerTargetInstantiationModelPointcut( this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory); this.lazy = true; } else { // A singleton aspect. this.pointcut = this.declaredPointcut; this.lazy = false; this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut); } }
// If we get here, we know we have an AspectJ method. // Check that it's an AspectJ-annotated class if (!isAspect(candidateAspectClass)) { thrownewAopConfigException("Advice must be declared inside an aspect type: " + "Offending method '" + candidateAdviceMethod + "' in class [" + candidateAspectClass.getName() + "]"); }
if (logger.isDebugEnabled()) { logger.debug("Found AspectJ method: " + candidateAdviceMethod); }
AbstractAspectJAdvice springAdvice;
// 根据不同的注解类型封装不同的增强器 switch (aspectJAnnotation.getAnnotationType()) { case AtBefore: springAdvice = newAspectJMethodBeforeAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); break; case AtAfter: springAdvice = newAspectJAfterAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); break; case AtAfterReturning: springAdvice = newAspectJAfterReturningAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); AfterReturningafterReturningAnnotation= (AfterReturning) aspectJAnnotation.getAnnotation(); if (StringUtils.hasText(afterReturningAnnotation.returning())) { springAdvice.setReturningName(afterReturningAnnotation.returning()); } break; case AtAfterThrowing: springAdvice = newAspectJAfterThrowingAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); AfterThrowingafterThrowingAnnotation= (AfterThrowing) aspectJAnnotation.getAnnotation(); if (StringUtils.hasText(afterThrowingAnnotation.throwing())) { springAdvice.setThrowingName(afterThrowingAnnotation.throwing()); } break; case AtAround: springAdvice = newAspectJAroundAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); break; case AtPointcut: if (logger.isDebugEnabled()) { logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'"); } returnnull; default: thrownewUnsupportedOperationException( "Unsupported advice type on method: " + candidateAdviceMethod); }
// Now to configure the advice... springAdvice.setAspectName(aspectName); springAdvice.setDeclarationOrder(declarationOrder); String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod); if (argNames != null) { springAdvice.setArgumentNamesFromStringArray(argNames); } springAdvice.calculateArgumentBindings(); return springAdvice; }
/** * Build a {@link org.springframework.aop.aspectj.DeclareParentsAdvisor} * for the given introduction field. * <p>Resulting Advisors will need to be evaluated for targets. * @param introductionField the field to introspect * @return {@code null} if not an Advisor */ private Advisor getDeclareParentsAdvisor(Field introductionField) { DeclareParentsdeclareParents= introductionField.getAnnotation(DeclareParents.class); if (declareParents == null) { // Not an introduction field returnnull; }
if (DeclareParents.class == declareParents.defaultImpl()) { thrownewIllegalStateException("'defaultImpl' attribute must be set on DeclareParents"); }
/** * Search the given candidate Advisors to find all Advisors that * can apply to the specified bean. * @param candidateAdvisors the candidate Advisors * @param beanClass the target's bean class * @param beanName the target's bean name * @return the List of applicable Advisors * @see ProxyCreationContext#getCurrentProxiedBeanName() */ protected List<Advisor> findAdvisorsThatCanApply( List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
/** * Determine the sublist of the {@code candidateAdvisors} list * that is applicable to the given class. * @param candidateAdvisors the Advisors to evaluate * @param clazz the target class * @return sublist of Advisors that can apply to an object of the given class * (may be the incoming List as-is) */ publicstatic List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) { if (candidateAdvisors.isEmpty()) { return candidateAdvisors; } List<Advisor> eligibleAdvisors = newLinkedList<Advisor>(); // 首先处理引介增强 for (Advisor candidate : candidateAdvisors) { if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) { eligibleAdvisors.add(candidate); } } booleanhasIntroductions= !eligibleAdvisors.isEmpty(); for (Advisor candidate : candidateAdvisors) { // 引介增强已被处理 if (candidate instanceof IntroductionAdvisor) { // already processed continue; } // 对于普通 bean 的处理 if (canApply(candidate, clazz, hasIntroductions)) { eligibleAdvisors.add(candidate); } } return eligibleAdvisors; }
findAdvisorsThatCanApply 函数的主要功能是寻找所有增强器中适用于当前 class 的增强器。引介增强与普通的增强是处理不一样的,所以分开处理。而对于真正的匹配在 canApply 中实现。
/** * Create an AOP proxy for the given bean. * @param beanClass the class of the bean * @param beanName the name of the bean * @param specificInterceptors the set of interceptors that is * specific to this bean (may be empty, but not null) * @param targetSource the TargetSource for the proxy, * already pre-configured to access the bean * @return the AOP proxy for the bean * @see #buildAdvisors */ protected Object createProxy( Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) { AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass); }
/** * Determine the advisors for the given bean, including the specific interceptors * as well as the common interceptor, all adapted to the Advisor interface. * @param beanName the name of the bean * @param specificInterceptors the set of interceptors that is * specific to this bean (may be empty, but not null) * @return the list of Advisors for the given bean */ protected Advisor[] buildAdvisors(String beanName, Object[] specificInterceptors) { // Handle prototypes correctly... Advisor[] commonInterceptors = resolveInterceptorNames();
List<Object> allInterceptors = newArrayList<Object>(); if (specificInterceptors != null) { // 加入拦截器 allInterceptors.addAll(Arrays.asList(specificInterceptors)); if (commonInterceptors.length > 0) { if (this.applyCommonInterceptorsFirst) { allInterceptors.addAll(0, Arrays.asList(commonInterceptors)); } else { allInterceptors.addAll(Arrays.asList(commonInterceptors)); } } } if (logger.isDebugEnabled()) { intnrOfCommonInterceptors= commonInterceptors.length; intnrOfSpecificInterceptors= (specificInterceptors != null ? specificInterceptors.length : 0); logger.debug("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors + " common interceptors and " + nrOfSpecificInterceptors + " specific interceptors"); }
@Override public Advisor wrap(Object adviceObject)throws UnknownAdviceTypeException { // 如果要封装的对象本身就是 Advisor 类型的那么无需再做过多处理 if (adviceObject instanceof Advisor) { return (Advisor) adviceObject; } // 因为此封装方法只对 Advisor 与 Advice 两种类型的数据有效,如果不是将不能封装 if (!(adviceObject instanceof Advice)) { thrownewUnknownAdviceTypeException(adviceObject); } Adviceadvice= (Advice) adviceObject; if (advice instanceof MethodInterceptor) { // So well-known it doesn't even need an adapter. // 如果是 MethodInterceptor 类型则使用 DefaultPointcutAdvisor 封装 returnnewDefaultPointcutAdvisor(advice); } // 如果存在 Advisor 的适配器那么也同样需要进行封装 for (AdvisorAdapter adapter : this.adapters) { // Check that it is supported. if (adapter.supportsAdvice(advice)) { returnnewDefaultPointcutAdvisor(advice); } } thrownewUnknownAdviceTypeException(advice); }
之前上文所说的适配器流程便在这里了。
由于 Spring 中涉及过多的拦截器、增强器、增强方法等方式来对逻辑进行增强,所以非常有必要统一封装成 Advisor 来进行代理的创建,完成了增强的封装过程,那么解析最重要的一步就是代理的创建与获取了。
ProxyFactory#getProxy
1 2 3
public Object getProxy() { return createAopProxy().getProxy(); }
创建代理
1 2 3 4 5 6 7 8 9 10
/** * Subclasses should call this to get a new AOP proxy. They should <b>not</b> * create an AOP proxy with {@code this} as an argument. */ protectedfinalsynchronized AopProxy createAopProxy() { if (!this.active) { activate(); } return getAopProxyFactory().createAopProxy(this); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
@Override public AopProxy createAopProxy(AdvisedSupport config)throws AopConfigException { // 见下文描述 if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { Class<?> targetClass = config.getTargetClass(); if (targetClass == null) { thrownewAopConfigException("TargetSource cannot determine target class: " + "Either an interface or a target is required for proxy creation."); } if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { returnnewJdkDynamicAopProxy(config); } returnnewObjenesisCglibAopProxy(config); } else { returnnewJdkDynamicAopProxy(config); } }
从 if 语句可以看出有三个方面影响 Spring 选择 JDKProxy or CglibProxy:
/** * Implementation of {@code InvocationHandler.invoke}. * <p>Callers will see exactly the exception thrown by the target, * unless a hook method throws an exception. */ @Override public Object invoke(Object proxy, Method method, Object[] args)throws Throwable { MethodInvocation invocation; ObjectoldProxy=null; booleansetProxyContext=false;
try { // equals 方法的处理 if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { // The target does not implement the equals(Object) method itself. return equals(args[0]); } // hash 方法的处理 elseif (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { // The target does not implement the hashCode() method itself. return hashCode(); } elseif (method.getDeclaringClass() == DecoratingProxy.class) { // There is only getDecoratedClass() declared -> dispatch to proxy config. return AopProxyUtils.ultimateTargetClass(this.advised); } // isAssignableFrom(Class cls) 方法如果调用这个方法的 class 或者接口与其参数 // 表示的类或接口相同或者是参数 cls 表示的类或接口的父类,则返回 true elseif (!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; }
// May be null. Get as late as possible to minimize the time we "own" the target, // in case it comes from a pool. target = targetSource.getTarget(); if (target != null) { targetClass = target.getClass(); }
// 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... // 将拦截器封装在 ReflectiveMethodInvocation,以便于使用其 proceed // 进行链接表用拦截器 invocation = newReflectiveMethodInvocation(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; } elseif (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) { thrownewAopInvocationException( "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); } } }
@Override public Object proceed()throws Throwable { // We start with an index of -1 and increment early. // 执行完所有增强后执行切点方法 if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { return invokeJoinpoint(); }
// 获取下一个要执行的拦截器 ObjectinterceptorOrInterceptionAdvice= 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. // 动态匹配 InterceptorAndDynamicMethodMatcherdm= (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice; if (dm.methodMatcher.matches(this.method, this.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. /** * 普通拦截器,直接调用拦截器,比如: * ExposeInvocationInterceptor * DelegatePerTargetObjectIntroductionInterceptor, * MethodBeforeAdviceInterceptor * AspectJAroundAdvice * AspectJAfterAdvice **/ // 将 this 作为参数传递以保证当前实例中调用链的执行 return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); } }
@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");
// 设置拦截器 Callback[] callbacks = getCallbacks(rootClass); Class<?>[] types = newClass<?>[callbacks.length]; for (intx=0; x < types.length; x++) { types[x] = callbacks[x].getClass(); } // fixedInterceptorMap only populated at this point, after getCallbacks call above enhancer.setCallbackFilter(newProxyCallbackFilter( 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 ex) { thrownewAopConfigException("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) { thrownewAopConfigException("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 (Throwable ex) { // TargetSource.getTarget() failed thrownewAopConfigException("Unexpected AOP exception", ex); } }
private Callback[] getCallbacks(Class<?> rootClass) throws Exception { // Parameters used for optimization choices... booleanexposeProxy=this.advised.isExposeProxy(); booleanisFrozen=this.advised.isFrozen(); booleanisStatic=this.advised.getTargetSource().isStatic();
// Choose an "aop" interceptor (used for AOP calls). // 将拦截器封装在 DynamicAdvisedInterceptor CallbackaopInterceptor=newDynamicAdvisedInterceptor(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 ? newStaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) : newDynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()); } else { targetInterceptor = isStatic ? newStaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) : newDynamicUnadvisedInterceptor(this.advised.getTargetSource()); }
// Choose a "direct to target" dispatcher (used for // unadvised calls to static targets that cannot return this). CallbacktargetDispatcher= isStatic ? newStaticDispatcher(this.advised.getTargetSource().getTarget()) : newSerializableNoOp();
Callback[] mainCallbacks = newCallback[] { // 将拦截器链加入 Callback 中 aopInterceptor, // for normal advice targetInterceptor, // invoke target without considering advice, if optimized newSerializableNoOp(), // no override for methods mapped to this targetDispatcher, this.advisedDispatcher, newEqualsInterceptor(this.advised), newHashCodeInterceptor(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 = newCallback[methods.length]; this.fixedInterceptorMap = newHashMap<String, Integer>(methods.length);
// TODO: small memory optimization here (can skip creation for methods with no advice) for (intx=0; x < methods.length; x++) { List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass); fixedCallbacks[x] = newFixedChainStaticTargetInterceptor( 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 = newCallback[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; }
@Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy)throws Throwable { ObjectoldProxy=null; booleansetProxyContext=false; Class<?> targetClass = null; Objecttarget=null; try { if (this.advised.exposeProxy) { // Make invocation available if necessary. oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } // May be null. Get as late as possible to minimize the time we // "own" the target, in case it comes from a pool... target = getTarget(); if (target != null) { targetClass = target.getClass(); } // 获取拦截器链 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 = newCglibMethodInvocation(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); } } }