相关内容:
架构师系列内容:架构师学习笔记(持续更新)
一步一步手绘Spring IOC运行时序图一(Spring 核心容器 IOC初始化过程)
一步一步手绘Spring IOC运行时序图二(基于XML的IOC容器初始化)
一步一步手绘Spring IOC运行时序图三(基于Annotation的IOC容器初始化)
一步一步手绘Spring DI运行时序图(Spring 自动装配之依赖注入)
一步一步手绘Spring AOP运行时序图(Spring AOP 源码分析)
一步一步手绘Spring MVC运行时序图(Spring MVC原理)
Spring MVC 使用优化建议

Spring AOP 源码分析

主要流程

时序图

创建代理对象导数第一个类写错了,应该为DefaultAopProxyFactory

寻找入口

Spring 的 AOP 是通过接入 BeanPostProcessor 后置处理器开始的,它是 Spring IOC 容器经常使用到的一个特性,这个 Bean 后置处理器是一个监听器,可以监听容器触发的 Bean 声明周期事件。后置处理器向容器注册以后,容器中管理的 Bean 就具备了接收 IOC 容器事件回调的能力。
BeanPostProcessor 的使用非常简单,只需要提供一个实现接口 BeanPostProcessor 的实现类,然后在 Bean 的配置文件中设置即可。

1、BeanPostProcessor 源码

public interface BeanPostProcessor {//为在Bean的初始化前提供回调入口@Nullabledefault Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {return bean;}//为在Bean的初始化之后提供回调入口@Nullabledefault Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {return bean;}
}

这两个回调的入口都是和容器管理的 Bean 的生命周期事件紧密相关,可以为用户提供在 Spring IOC容器初始化 Bean 过程中自定义的处理操作。

2、AbstractAutowireCapableBeanFactory 类对容器生成的 Bean 添加后置处理器

BeanPostProcessor 后置处理器的调用发生在 Spring IOC 容器完成对 Bean 实例对象的创建和属性的依赖注入完成之后,在对 Spring 依赖注入的源码分析过程中我们知道,当应用程序第一次调用 getBean()方法(lazy-init 预实例化除外)向 Spring IOC 容器索取指定 Bean 时触发 Spring IOC 容器创建 Bean 实例对象并进行依赖注入的过程,其中真正实现创建 Bean 对象并进行依赖注入的方法是AbstractAutowireCapableBeanFactory 类的 doCreateBean()方法,主要源码如下:

//真正创建Bean的方法
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)throws BeanCreationException {// Instantiate the bean.//封装被创建的Bean对象BeanWrapper instanceWrapper = null;if (mbd.isSingleton()) {instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);}if (instanceWrapper == null) {instanceWrapper = createBeanInstance(beanName, mbd, args);}final Object bean = instanceWrapper.getWrappedInstance();//获取实例化对象的类型Class<?> beanType = instanceWrapper.getWrappedClass();if (beanType != NullBean.class) {mbd.resolvedTargetType = beanType;}// Allow post-processors to modify the merged bean definition.//调用PostProcessor后置处理器synchronized (mbd.postProcessingLock) {if (!mbd.postProcessed) {try {applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);}catch (Throwable ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Post-processing of merged bean definition failed", ex);}mbd.postProcessed = true;}}// Eagerly cache singletons to be able to resolve circular references// even when triggered by lifecycle interfaces like BeanFactoryAware.//向容器中缓存单例模式的Bean对象,以防循环引用boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&isSingletonCurrentlyInCreation(beanName));if (earlySingletonExposure) {if (logger.isDebugEnabled()) {logger.debug("Eagerly caching bean '" + beanName +"' to allow for resolving potential circular references");}//这里是一个匿名内部类,为了防止循环引用,尽早持有对象的引用addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));}// Initialize the bean instance.//Bean对象的初始化,依赖注入在此触发//这个exposedObject在初始化完成之后返回作为依赖注入完成后的BeanObject exposedObject = bean;try {//对 Bean 属性进行依赖注入populateBean(beanName, mbd, instanceWrapper);//在对 Bean 实例对象生成和依赖注入完成以后, 开始对 Bean 实例对象//进行初始化 , 为 Bean 实例对象应用 BeanPostProcessor 后置处理器exposedObject = initializeBean(beanName, exposedObject, mbd);}catch (Throwable ex) {if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {throw (BeanCreationException) ex;}else {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);}}if (earlySingletonExposure) {//获取指定名称的已注册的单例模式Bean对象Object earlySingletonReference = getSingleton(beanName, false);if (earlySingletonReference != null) {//根据名称获取的已注册的Bean和正在实例化的Bean是同一个if (exposedObject == bean) {//当前实例化的Bean初始化完成exposedObject = earlySingletonReference;}//当前Bean依赖其他Bean,并且当发生循环引用时不允许新创建实例对象else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {String[] dependentBeans = getDependentBeans(beanName);Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);//获取当前Bean所依赖的其他Beanfor (String dependentBean : dependentBeans) {//对依赖Bean进行类型检查if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {actualDependentBeans.add(dependentBean);}}if (!actualDependentBeans.isEmpty()) {throw new BeanCurrentlyInCreationException(beanName,"Bean with name '" + beanName + "' has been injected into other beans [" +StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +"] in its raw version as part of a circular reference, but has eventually been " +"wrapped. This means that said other beans do not use the final version of the " +"bean. This is often the result of over-eager type matching - consider using " +"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");}}}}// Register bean as disposable.//注册完成依赖注入的Beantry {registerDisposableBeanIfNecessary(beanName, bean, mbd);}catch (BeanDefinitionValidationException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);}//为应用返回所需要的实例对象return exposedObject;
}

从上面的代码中我们知道,为 Bean 实例对象添加 BeanPostProcessor 后置处理器的入口的是initializeBean()方法。

3、initializeBean()方法为容器产生的 Bean 实例对象添加 BeanPostProcessor 后置处理器

同样在 AbstractAutowireCapableBeanFactory 类中,initializeBean()方法实现为容器创建的 Bean实例对象添加 BeanPostProcessor 后置处理器,源码如下:

//初始容器创建的Bean实例对象,为其添加BeanPostProcessor后置处理器
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {//JDK的安全机制验证权限if (System.getSecurityManager() != null) {//实现PrivilegedAction接口的匿名内部类AccessController.doPrivileged((PrivilegedAction<Object>) () -> {invokeAwareMethods(beanName, bean);return null;}, getAccessControlContext());}else {//为Bean实例对象包装相关属性,如名称,类加载器,所属容器等信息invokeAwareMethods(beanName, bean);}Object wrappedBean = bean;//对BeanPostProcessor后置处理器的postProcessBeforeInitialization//回调方法的调用,为Bean实例初始化前做一些处理if (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);}//调用Bean实例对象初始化的方法,这个初始化方法是在Spring Bean定义配置//文件中通过init-method属性指定的try {invokeInitMethods(beanName, wrappedBean, mbd);}catch (Throwable ex) {throw new BeanCreationException((mbd != null ? mbd.getResourceDescription() : null),beanName, "Invocation of init method failed", ex);}//对BeanPostProcessor后置处理器的postProcessAfterInitialization//回调方法的调用,为Bean实例初始化之后做一些处理if (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}return wrappedBean;
}
@Override
//调用BeanPostProcessor后置处理器实例对象初始化之后的处理方法
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)throws BeansException {Object result = existingBean;//遍历容器为所创建的Bean添加的所有BeanPostProcessor后置处理器for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {//调用Bean实例所有的后置处理中的初始化后处理方法,为Bean实例对象在//初始化之后做一些自定义的处理操作Object current = beanProcessor.postProcessAfterInitialization(result, beanName);if (current == null) {return result;}result = current;}return result;
}

BeanPostProcessor 是一个接口,其初始化前的操作方法和初始化后的操作方法均委托其实现子类来实现,在 Spring 中,BeanPostProcessor 的实现子类非常的多,分别完成不同的操作,如:AOP 面向切面编程的注册通知适配器、Bean 对象的数据校验、Bean 继承属性、方法的合并等等,我们以最简单的AOP 切面织入来简单了解其主要的功能。下面我们来分析其中一个创建 AOP 代理对象的子类AbstractAutoProxyCreator 类。该类重写了 postProcessAfterInitialization()方法。

选择代理策略

进入 postProcessAfterInitialization()方法,我们发现调到了一个非常核心的方法 wrapIfNecessary(),其源码如下:

@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {if (bean != null) {Object cacheKey = getCacheKey(bean.getClass(), beanName);if (!this.earlyProxyReferences.contains(cacheKey)) {return wrapIfNecessary(bean, beanName, cacheKey);}}return bean;
}protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {return bean;}//判断是否不应该代理这个 beanif (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// Create proxy if we have 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;}this.advisedBeans.put(cacheKey, Boolean.FALSE);return bean;
}/**
* 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, @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());
}

整个过程跟下来,我发现最终调用的是 proxyFactory.getProxy()方法。到这里我们大概能够猜到proxyFactory 有 JDK 和 CGLib 的,那么我们该如何选择呢?最终调用的是 DefaultAopProxyFactory的 createAopProxy()方法:

public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {@Overridepublic AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {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.");}if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {return new JdkDynamicAopProxy(config);}return new ObjenesisCglibAopProxy(config);}else {return new JdkDynamicAopProxy(config);}}/*** Determine whether the supplied {@link AdvisedSupport} has only the* {@link org.springframework.aop.SpringProxy} interface specified* (or no proxy interfaces specified at all).*/private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {Class<?>[] ifcs = config.getProxiedInterfaces();return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));}}

调用代理方法

分析调用逻辑之前先上类图,看看 Spring 中主要的 AOP 组件:

上面我们已经了解到 Spring 提供了两种方式来生成代理方式有 JDKProxy 和 CGLib。下面我们来研究一下 Spring 如何使用 JDK 来生成代理对象,具体的生成代码放在 JdkDynamicAopProxy 这个类中,直接上相关代码:

/**
* 获取代理类要实现的接口,除了Advised对象中配置的,还会加上SpringProxy, Advised(opaque=false)
* 检查上面得到的接口中有没有定义 equals或者hashcode的接口
* 调用Proxy.newProxyInstance创建代理对象
*/
@Override
public Object getProxy(@Nullable 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);
}

通过注释我们应该已经看得非常明白代理对象的生成过程,此处不再赘述。下面的问题是,代理对象生成了,那切面是如何织入的?

我们知道 InvocationHandler 是 JDK 动态代理的核心,生成的代理对象的方法调用都会委托到InvocationHandler.invoke()方法。而从 JdkDynamicAopProxy 的源码我们可以看到这个类其实也实现了 InvocationHandler,下面我们分析 Spring AOP 是如何织入切面的,直接上源码看 invoke()方法:

@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {MethodInvocation invocation;Object oldProxy = null;boolean setProxyContext = false;TargetSource targetSource = this.advised.targetSource;Object target = null;try {//eqauls()方法,具目标对象未实现此方法if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {// The target does not implement the equals(Object) method itself.return equals(args[0]);}//hashCode()方法,具目标对象未实现此方法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);}//Advised接口或者其父接口中定义的方法,直接反射调用,不应用通知else if (!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;}// 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.//获取可以应用到此方法上的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.//如果没有可以应用到此方法的通知(Interceptor),此直接反射调用 method.invoke(target, args)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...//创建MethodInvocationinvocation = 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);}}
}

主要实现思路可以简述为:首先获取应用到此方法上的通知链(Interceptor Chain)。如果有通知,则应用通知,并执行 JoinPoint;如果没有通知,则直接反射执行 JoinPoint。而这里的关键是通知链是如何获取的以及它又是如何执行的呢?现在来逐一分析。首先,从上面的代码可以看到,通知链是通过Advised.getInterceptorsAndDynamicInterceptionAdvice()这个方法来获取的,我们来看下这个方法的实现逻辑:

/**
* Determine a list of {@link org.aopalliance.intercept.MethodInterceptor} objects
* for the given method, based on this configuration.
* @param method the proxied method
* @param targetClass the target class
* @return List of MethodInterceptors (may also include InterceptorAndDynamicMethodMatchers)
*/
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;
}

通过上面的源码我们可以看到,实际获取通知的实现逻辑其实是由 AdvisorChainFactory 的实现类DefaultAdvisorChainFactory的getInterceptorsAndDynamicInterceptionAdvice()方法来完成的,且获取到的结果会被缓存。下面来分析 getInterceptorsAndDynamicInterceptionAdvice()方法的实现

/**
* 从提供的配置实例config中获取advisor列表,遍历处理这些advisor.如果是IntroductionAdvisor,
* 则判断此Advisor能否应用到目标类targetClass上.如果是PointcutAdvisor,则判断
* 此Advisor能否应用到目标方法method上.将满足条件的Advisor通过AdvisorAdaptor转化成Interceptor列表返回.
*/
@Override
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.List<Object> interceptorList = new ArrayList<>(config.getAdvisors().length);Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());//查看是否包含IntroductionAdvisorboolean hasIntroductions = hasMatchingIntroductions(config, actualClass);//这里实际上注册一系列AdvisorAdapter,用于将Advisor转化成MethodInterceptorAdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();for (Advisor advisor : config.getAdvisors()) {if (advisor instanceof PointcutAdvisor) {// Add it conditionally.PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {//这个地方这两个方法的位置可以互换下//将Advisor转化成InterceptorMethodInterceptor[] interceptors = registry.getInterceptors(advisor);//检查当前advisor的pointcut是否可以匹配当前方法MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {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) {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;
}

这个方法执行完成后,Advised 中配置能够应用到连接点(JoinPoint)或者目标类(Target Object)的 Advisor 全部被转化成了 MethodInterceptor,接下来我们再看下得到的拦截器链是怎么起作用的。
回到JdkDynamicAopProxy.invoke 接着advised.getInterceptorsAndDynamicInterceptionAdvice 方法继续看

// 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.
//如果没有可以应用到此方法的通知(Interceptor),此直接反射调用 method.invoke(target, args)
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...//创建MethodInvocationinvocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);// Proceed to the joinpoint through the interceptor chain.retVal = invocation.proceed();
}

从这段代码可以看出,如果得到的拦截器链为空,则直接反射调用目标方法,否则创建MethodInvocation,调用其 proceed()方法,触发拦截器链的执行,来看下具体代码:

@Override
@Nullable
public Object proceed() throws Throwable {// We start with an index of -1 and increment early.//如果Interceptor执行完了,则执行joinPointif (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {return invokeJoinpoint();}Object interceptorOrInterceptionAdvice =this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);//如果要动态匹配joinPointif (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {// Evaluate dynamic method matcher here: static part will already have// been evaluated and found to match.InterceptorAndDynamicMethodMatcher dm =(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.//动态匹配失败时,略过当前Intercetpor,调用下一个Interceptorreturn proceed();}}else {// It's an interceptor, so we just invoke it: The pointcut will have// been evaluated statically before this object was constructed.//执行当前Intercetporreturn ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);}
}

至此,通知链就完美地形成了。我们再往下来看 invokeJoinpointUsingReflection()方法,其实就是反射调用:

//如果Interceptor执行完了,则执行joinPoint
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {return invokeJoinpoint();
}
@Nullable
protected Object invokeJoinpoint() throws Throwable {return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);
}@Nullable
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);}
}

触发通知

在为 AopProxy 代理对象配置拦截器的实现中,有一个取得拦截器的配置过程,这个过程是由 DefaultAdvisorChainFactory 实现的,这个工厂类负责生成拦截器链,在它的getInterceptorsAndDynamicInterceptionAdvice 方法中,有一个适配器和注册过程,通过配置 Spring 预先设计好的拦截器,Spring 加入了它对 AOP 实现的处理。

/**
* 从提供的配置实例config中获取advisor列表,遍历处理这些advisor.如果是IntroductionAdvisor,
* 则判断此Advisor能否应用到目标类targetClass上.如果是PointcutAdvisor,则判断
* 此Advisor能否应用到目标方法method上.将满足条件的Advisor通过AdvisorAdaptor转化成Interceptor列表返回.
*/
@Override
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.List<Object> interceptorList = new ArrayList<>(config.getAdvisors().length);Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());//查看是否包含IntroductionAdvisorboolean hasIntroductions = hasMatchingIntroductions(config, actualClass);//这里实际上注册一系列AdvisorAdapter,用于将Advisor转化成MethodInterceptorAdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();...return interceptorList;
}

GlobalAdvisorAdapterRegistry 负责拦截器的适配和注册过程。

package org.springframework.aop.framework.adapter;public abstract class GlobalAdvisorAdapterRegistry {/*** Keep track of a single instance so we can return it to classes that request it.*/private static AdvisorAdapterRegistry instance = new DefaultAdvisorAdapterRegistry();/*** Return the singleton {@link DefaultAdvisorAdapterRegistry} instance.*/public static AdvisorAdapterRegistry getInstance() {return instance;}/*** Reset the singleton {@link DefaultAdvisorAdapterRegistry}, removing any* {@link AdvisorAdapterRegistry#registerAdvisorAdapter(AdvisorAdapter) registered}* adapters.*/static void reset() {instance = new DefaultAdvisorAdapterRegistry();}}

而GlobalAdvisorAdapterRegistry 起到了适配器和单例模式的作用,提供了一个DefaultAdvisorAdapterRegistry,它用来完成各种通知的适配和注册过程。

@SuppressWarnings("serial")
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {private final List<AdvisorAdapter> adapters = new ArrayList<>(3);/*** Create a new DefaultAdvisorAdapterRegistry, registering well-known adapters.*/public DefaultAdvisorAdapterRegistry() {registerAdvisorAdapter(new MethodBeforeAdviceAdapter());registerAdvisorAdapter(new AfterReturningAdviceAdapter());registerAdvisorAdapter(new ThrowsAdviceAdapter());}@Overridepublic Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {if (adviceObject instanceof Advisor) {return (Advisor) adviceObject;}if (!(adviceObject instanceof Advice)) {throw new UnknownAdviceTypeException(adviceObject);}Advice advice = (Advice) adviceObject;if (advice instanceof MethodInterceptor) {// So well-known it doesn't even need an adapter.return new DefaultPointcutAdvisor(advice);}for (AdvisorAdapter adapter : this.adapters) {// Check that it is supported.if (adapter.supportsAdvice(advice)) {return new DefaultPointcutAdvisor(advice);}}throw new UnknownAdviceTypeException(advice);}@Overridepublic MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {List<MethodInterceptor> interceptors = new ArrayList<>(3);Advice advice = advisor.getAdvice();if (advice instanceof MethodInterceptor) {interceptors.add((MethodInterceptor) advice);}for (AdvisorAdapter adapter : this.adapters) {if (adapter.supportsAdvice(advice)) {interceptors.add(adapter.getInterceptor(advisor));}}if (interceptors.isEmpty()) {throw new UnknownAdviceTypeException(advisor.getAdvice());}return interceptors.toArray(new MethodInterceptor[interceptors.size()]);}@Overridepublic void registerAdvisorAdapter(AdvisorAdapter adapter) {this.adapters.add(adapter);}}

DefaultAdvisorAdapterRegistry 设置了一系列的是配置,正是这些适配器的实现,为Spring AOP 提供了编织能力。下面以 MethodBeforeAdviceAdapter 为例,看具体的实现:

@SuppressWarnings("serial")
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {@Overridepublic boolean supportsAdvice(Advice advice) {return (advice instanceof MethodBeforeAdvice);}@Overridepublic MethodInterceptor getInterceptor(Advisor advisor) {MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();return new MethodBeforeAdviceInterceptor(advice);}}

Spring AOP 为了实现 advice 的织入,设计了特定的拦截器对这些功能进行了封装。我们接着看 MethodBeforeAdviceInterceptor 如何完成封装的?

@SuppressWarnings("serial")
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {private MethodBeforeAdvice advice;public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {Assert.notNull(advice, "Advice must not be null");this.advice = advice;}@Overridepublic Object invoke(MethodInvocation mi) throws Throwable {this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );return mi.proceed();}
}

可以看到,invoke 方法中,首先触发了 advice 的 before 回调,然后才是 proceed。AfterReturningAdviceInterceptor 的源码

@SuppressWarnings("serial")
public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {private final AfterReturningAdvice advice;public AfterReturningAdviceInterceptor(AfterReturningAdvice advice) {Assert.notNull(advice, "Advice must not be null");this.advice = advice;}@Overridepublic Object invoke(MethodInvocation mi) throws Throwable {Object retVal = mi.proceed();this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());return retVal;}}

ThrowsAdviceInterceptor 的源码:

public class ThrowsAdviceInterceptor implements MethodInterceptor, AfterAdvice {@Overridepublic Object invoke(MethodInvocation mi) throws Throwable {try {return mi.proceed();}catch (Throwable ex) {Method handlerMethod = getExceptionHandler(ex);if (handlerMethod != null) {invokeHandlerMethod(mi, ex, handlerMethod);}throw ex;}}private void invokeHandlerMethod(MethodInvocation mi, Throwable ex, Method method) throws Throwable {Object[] handlerArgs;if (method.getParameterCount() == 1) {handlerArgs = new Object[] { ex };}else {handlerArgs = new Object[] {mi.getMethod(), mi.getArguments(), mi.getThis(), ex};}try {method.invoke(this.throwsAdvice, handlerArgs);}catch (InvocationTargetException targetEx) {throw targetEx.getTargetException();}}}

一步一步手绘Spring AOP运行时序图(Spring AOP 源码分析)相关推荐

  1. 一步一步手绘Spring MVC运行时序图(Spring MVC原理)

    相关内容: 架构师系列内容:架构师学习笔记(持续更新) 一步一步手绘Spring IOC运行时序图一(Spring 核心容器 IOC初始化过程) 一步一步手绘Spring IOC运行时序图二(基于XM ...

  2. 一步一步手绘Spring DI运行时序图(Spring 自动装配之依赖注入)

    相关内容: 架构师系列内容:架构师学习笔记(持续更新) 一步一步手绘Spring IOC运行时序图一(Spring 核心容器 IOC初始化过程) 一步一步手绘Spring IOC运行时序图二(基于XM ...

  3. 一步一步手绘Spring IOC运行时序图一(Spring 核心容器 IOC初始化过程)

    相关内容: 架构师系列内容:架构师学习笔记(持续更新) 一步一步手绘Spring IOC运行时序图一(Spring 核心容器 IOC初始化过程) 一步一步手绘Spring IOC运行时序图二(基于XM ...

  4. 一步一步手绘Spring IOC运行时序图三(基于Annotation的IOC容器初始化)

    相关内容: 架构师系列内容:架构师学习笔记(持续更新) 一步一步手绘Spring IOC运行时序图一(Spring 核心容器 IOC初始化过程) 一步一步手绘Spring IOC运行时序图二(基于XM ...

  5. 一步一步手绘Spring IOC运行时序图二(基于XML的IOC容器初始化)

    相关内容: 架构师系列内容:架构师学习笔记(持续更新) 一步一步手绘Spring IOC运行时序图一(Spring 核心容器 IOC初始化过程) 一步一步手绘Spring IOC运行时序图二(基于XM ...

  6. 一步一步手绘Spring MVC运行时序图

    Spring MVC 初体验 初探Spring MVC 请求处理流程 Spring MVC 相对于前面的章节算是比较简单的,我们首先引用<Spring in Action>上 的一张图来了 ...

  7. 21.手绘Spring IOC运行时序图

    1.再谈IOC与 DI IOC(lnversion of Control)控制反转:所谓控制反转,就是把原先我们代码里面需要实现的对象创 建.依赖的代码,反转给容器来帮忙实现.那么必然的我们需要创建一 ...

  8. Spring IOC和Bean生命周期以及源码分析

    这篇文章主要讲解 IOC 容器的创建过程,让大家对整体有一个全局的认识,文章目录如图: 1. 基础知识 1.1 什么是 Spring IOC ? IOC 不是一种技术,只是一种思想,一个重要的面向对象 ...

  9. 聊聊Spring中的数据绑定 --- DataBinder本尊(源码分析)

    每篇一句 唯有热爱和坚持,才能让你在程序人生中屹立不倒,切忌跟风什么语言或就学什么去~ 相关阅读 [小家Spring]聊聊Spring中的数据转换:Converter.ConversionServic ...

最新文章

  1. Windows下关于Composer使用时出现的问题及解决办法
  2. 使用java命令运行class文件提示“错误:找不到或无法加载主类“的问题分析
  3. c java python html_如何通俗地解释 C、C++、C#、Java、JavaScript、HTML、Python的用处
  4. P3206 [HNOI2010]城市建设
  5. 连接格点(信息学奥赛一本通-T1394)
  6. edge android apk下载地址,edge app下载-edge完整版v7.2.0 安卓版 - 极光下载站
  7. 2021大学生搭建阿里云服务器+域名申请流程--教程
  8. 适合初学者使用的Mac绘图软件推荐
  9. build constraints exclude all Go file GOland 导入“github.com/gin-gonic/gin“ 报红,
  10. matlab画心形线
  11. 计算机网络技术组装与维护,计算机组装与维护计算机网络技术2010(组网)课程标准.doc...
  12. 谁能和乔布斯比勤奋?乔布斯的睡眠时间
  13. Win10 OpenGL安装及配置
  14. 计算机应用研究抄袭撤稿,衢州畜牧兽医高级职称评审北大核心期刊书评发表
  15. html中auto是设置什么的,css中margin:auto什么意思?margin:auto属性的用法详解
  16. Linux小命令(8)usermod
  17. c语言——do……while循环
  18. matlab 实现二进制与十进制相互转换
  19. 电影订票网站的设计与开发
  20. CW,FM以及Chirp波

热门文章

  1. 高中理科不好学计算机,高一理科很差但想学理咋办
  2. pythonfor循环语句例子_Python for循环学习总结
  3. C++ 中的Virtual Function (虚函数)
  4. Java项目性能监控和调优工具-Javamelody
  5. 编译源码时出现 Checking API: checkapi-last (unknown): error 17解决方法
  6. 抓取网址中的信息(需要解码的)
  7. php 上传大文件主要涉及配置upload_max_filesize和post_max_size两个选项
  8. Duilib自定义控件
  9. SpringAOP 通知(adivce)- methodIntercepor
  10. 这一回,我们聊聊恐惧