Spring AOP 详解

举报
JavaEdge 发表于 2022/02/11 21:27:57 2022/02/11
【摘要】 1 AOP 应用场景AOP,Aspect Oriented Programming,面向切面编程。通过预编译和运行期动态代理,实现在不修改源代码情况下,给程序动态地统一添加功能。AOP设计追求调用者和被调用者之间的解耦,一些非业务,如:日志、事务、安全等都会写在业务代码中(也即是说,这些非业务类横切于业务类),但这些代码往往是重复,复制粘贴式的代码,会给程序维护带来不便,AOP 就实现了把...

1 AOP 应用场景

AOP,Aspect Oriented Programming,面向切面编程。通过预编译和运行期动态代理,实现在不修改源代码情况下,给程序动态地统一添加功能。

AOP设计追求调用者和被调用者之间的解耦,一些非业务,如:日志、事务、安全等都会写在业务代码中(也即是说,这些非业务类横切于业务类),但这些代码往往是重复,复制粘贴式的代码,会给程序维护带来不便,AOP 就实现了把这些业务需求与系统需求分开来做。这种解决的方式也称代理机制。

2 AOP 概念

1 切面(Aspect)

官方定义“ 一个关注点的模块化,这个关注点可能会横切多个对象” 。

“ 切面”可在ApplicationContext 中aop:aspect来配置(古老的 xml 配置方式)

连接点(Joinpoint)

程序执行过程中的某一行为,例如,xxxService .get 的调用或
xxxService .delete 抛出异常等行为。

通知(Advice)

“切面”对于某个“连接点”所产生的动作。其中,一个“切面”可以包含多个“Advice”。

切入点(Pointcut)

匹配连接点的断言,在AOP 中通知和一个切入点表达式关联。切面中的所有通知所关注的连接点,都由切入点表达式来决定。

目标对象(Target Object)

被一个或者多个切面所通知的对象。例如,AServcieImpl 和BServiceImpl,当然在实际运行时,Spring AOP 采用代理实现,实际AOP 操作的是TargetObject 的代理对象。

AOP 代理(AOP Proxy)

在Spring AOP 中有两种代理方式:

  • JDK 动态代理

  • CGLib 代理

    默认,TargetObject 实现了接口时,则采用JDK 动态代理;反之,采用CGLib 代理。

    强制使用CGLib 代理需要将aop:config的proxy-target-class 属性设为true。
    通知(Advice)类型:

6、前置通知(Before Advice)
在某连接点(JoinPoint)之前执行的通知,但这个通知不能阻止连接点前的执行。ApplicationContext
中在aop:aspect里面使用aop:before元素进行声明。例如,TestAspect 中的doBefore 方法。

7、后置通知(After Advice)
当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。ApplicationContext 中在
aop:aspect里面使用aop:after元素进行声明。例如,ServiceAspect 中的returnAfter 方法,所
以Teser 中调用UserService.delete 抛出异常时,returnAfter 方法仍然执行。

8、返回后通知(After Return Advice)
在某连接点正常完成后执行的通知,不包括抛出异常的情况。ApplicationContext 中在aop:aspect
里面使用元素进行声明。

9、环绕通知(Around Advice)
包围一个连接点的通知,类似Web 中Servlet 规范中的Filter 的doFilter 方法。可以在方法的调用前
后完成自定义的行为, 也可以选择不执行。ApplicationContext 中在aop:aspect 里面使用
aop:around元素进行声明。例如,ServiceAspect 中的around 方法。

异常通知(After Throwing Advice)

在方法抛出异常退出时执行的通知。ApplicationContext 中在aop:aspect 里面使用
aop:after-throwing元素进行声明。

可将多个通知应用到一个目标对象。使用Spring AOP 可以基于两种方式:

  • 方便和强大的注解方式
  • 古老的xml配置方式

3 配置方式

注解

在xml 文件中声明激活自动扫描组件功能,同时激活自动代理功能:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-2.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="com.gupaoedu"/>
<context:annotation-config />
</beans>

或者基于注解的:@SpringBootApplication(scanBasePackages = {“xxx”})

第二步,为Aspect 切面类添加注解。

4 Spring AOP 源码分析

入口

AOP 通过接入BeanPostProcessor开始的,BeanPostProcessor是个监听器,可监听容器触发的Bean生命周期事件。BeanPostProcessor向容器注册以后,容器中管理的Bean就具备了接收IOC容器事件回调的能力。

BeanPostProcessor使用非常简单,只需要提供一个实现接口BeanPostProcessor 的实现类,然后在Bean的配置文件中设置即可。

2 AbstractAu对容器生成的Bean添加后置处理器

BeanPostProcessor调用发生在IoC容器完成对Bean实例的创建和属性的依赖注入完成后。

当应用程序第一次调用getBean()(lazy-init预实例化除外)向IoC容器索取指定Bean时,触发Spring IOC 容器创建Bean实例并进行依赖注入的过程, 真正实现创建Bean并依赖注入的方法是AbstractAutowireCapableBeanFactory#doCreateBean():

// 真正创建Bean的方法
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
  throws BeanCreationException {

  // 实例化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;
  }

  // 调用PostProcessor
  synchronized (mbd.postProcessingLock) {
    if (!mbd.postProcessed) {
      try {
        applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
      }
      mbd.postProcessed = true;
    }
  }
  // 向Eagerly cache singletons容器中缓存单例Bean,以防循环依赖
  // even when triggered by lifecycle interfaces like BeanFactoryAware.
  boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                                    isSingletonCurrentlyInCreation(beanName));
  if (earlySingletonExposure) {
    // 匿名内部类,为了防止循环引用,持有Eagerly cache singletons容器中对象的引用
    addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
  }

  // bean实例的初始化,依赖注入在此触发
  // 这个exposedObject 在初始化完成之后返回,作为依赖注入完成后的Bean
  Object exposedObject = bean;
  try {
    //将Bean实例对象封装,并且Bean 定义中配置的属性值赋值给实例对象
    populateBean(beanName, mbd, instanceWrapper);
    // 初始化Bean,为Bean实例应用BeanPostProcessor
    exposedObject = initializeBean(beanName, exposedObject, mbd);
  }

  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 所依赖的其他Bean
        for (String dependentBean : dependentBeans) {
          //对依赖Bean 进行类型检查
          if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
            actualDependentBeans.add(dependentBean);
          }
        }
      }
    }
  }

  // Register bean as disposable.
  // 注册完成依赖注入的Bean
  try {
    registerDisposableBeanIfNecessary(beanName, bean, mbd);
  }
  return exposedObject;
}

为Bean实例添加BeanPostProcessor的入口是initializeBean()

3、initializeBean()

为容器创建的Bean实例添加BeanPostProcessor :

// 初始容器创建的Bean实例,为其添加BeanPostProcessor后置处理器
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
  if (System.getSecurityManager() != null) {
    ...
  }
  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;
}

//调用BeanPostProcessor 后置处理器实例对象初始化之前的处理方法
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
  throws BeansException {

  Object result = existingBean;
  //遍历容器为所创建的Bean 添加的所有BeanPostProcessor 后置处理器
  for (BeanPostProcessor processor : getBeanPostProcessors()) {
    //调用Bean 实例所有的后置处理中的初始化前处理方法,为Bean 实例对象在
    //初始化之前做一些自定义的处理操作
    Object current = processor.postProcessBeforeInitialization(result, beanName);
    if (current == null) {
      return result;
    }
    result = current;
  }
  return result;
}

//调用BeanPostProcessor 后置处理器实例对象初始化之后的处理方法
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
  throws BeansException {

  Object result = existingBean;
  //遍历容器为所创建的Bean 添加的所有BeanPostProcessor 后置处理器
  for (BeanPostProcessor processor : getBeanPostProcessors()) {
    //调用Bean 实例所有的后置处理中的初始化后处理方法,为Bean 实例对象在
    //初始化之后做一些自定义的处理操作
    Object current = processor.postProcessAfterInitialization(result, beanName);
    if (current == null) {
      return result;
    }
    result = current;
  }
  return result;
}

BeanPostProcessor 是个接口,其初始化前的操作方法和初始化后的操作方法均委托其实现子类来实
现,BeanPostProcessor子类很多:AOP 面向切面编程的注册通知适配器、Bean 对象的数据校验、Bean 继承属性、方法的合并等。

以最简单的AOP 切面织入来简单了解其主要的功能。下面分析其中一个创建AOP 代理对象的子类
AbstractAutoProxyCreator 类。该类重写了postProcessAfterInitialization()方法。

选择代理策略

postProcessAfterInitialization()调wrapIfNecessary():

@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
	if (bean != null) {
		Object cacheKey = getCacheKey(bean.getClass(), beanName);
		if (this.earlyProxyReferences.remove(cacheKey) != bean) {
			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;
	}
	// 判断是否不应该代理这个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
	// 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;
}

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 {

	@Override
	public 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:

@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
	if (logger.isTraceEnabled()) {
		logger.trace("Creating JDK dynamic proxy: " + 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 {
		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...
				//创建MethodInvocation
				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;
			}
			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()这个方法来获取的:

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#
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.
	//这里实际上注册一系列AdvisorAdapter,用于将Advisor 转化成MethodInterceptor
	AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
	Advisor[] advisors = config.getAdvisors();
	List<Object> interceptorList = new ArrayList<>(advisors.length);
	Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
	//查看是否包含IntroductionAdvisor
	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) {
							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。

得到的拦截器链是怎么起作用的。

		// 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...
			//创建MethodInvocation
			MethodInvocation invocation =
					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 执行完了,则执行joinPoint
		if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
			return invokeJoinpoint();
		}

		Object interceptorOrInterceptionAdvice =
				this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
		//如果要动态匹配joinPoint
		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.
				//动态匹配失败时,略过当前Intercetpor,调用下一个Interceptor
				return proceed();
			}
		}
		else {
			//执行当前Intercetpor
			// 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);
		}
	}

通知链形成,再往下invokeJoinpointUsingReflection(),反射调用:

@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);
	}
}

Spring AOP时序图

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。