首页 > 其他分享 >深入理解 SpringAOP(二):AOP的执行流程

深入理解 SpringAOP(二):AOP的执行流程

时间:2024-03-20 23:55:20浏览次数:28  
标签:拦截器 return 流程 Object 代理 bean Advisor AOP SpringAOP

概述

在之前的文章中,我们已经对 SpringAOP 的关键组件进行了描述,并且了解了其基本操作和流程。在本文中,我们将进一步深入源码,揭示 SpringAOP 的内部实现细节,理解其运行机制的每个环节,包括切面的织入方式、代理对象的创建过程、连接点的定位与匹配等。通过对完整运行流程的深入研究,我们能够更全面地理解 SpringAOP 的工作原理,并且能够更好地利用和扩展这一功能。

本专题共三篇文章,这是第二篇:

  • 深入理解 SpringAOP(一):AOP 组件概述
  • 深入理解 SpringAOP(二):AOP的执行流程;
  • 深入理解 SpringAOP(三):AspectJ支持;

一、代理生效时机

在前文,我们提到了代理基于 AbstractAutoProxyCreator 的子类生效,因此直接观察该类,我们可以注意到 AbstractAutoProxyCreator 中实现了 SmartInstantiationAwareBeanPostProcessor ,说明他可能在三个关键节点触发代理:

  • InstantiationAwareBeanPostProcessor :在实例化阶段,即 bean 实例化前后;
  • SmartInstantiationAwareBeanPostProcessor:早期引用创建阶段,即在循环依赖中,当 bean 已实例化而未被初始化时,被其他依赖它的 bean 通过 getEarlyBeanReference 方法从一级缓存中获取;
  • BeanPostProcessor:在初始化阶段,即 bean 完成初始化后,进行依赖注入与各种声明周期回调前后;

1、在实例化阶段

InstantiationAwareBeanPostProcessor 分别提供了 postProcessBeforeInstantiationpostProcessAfterInstantiation 两个方法用于介入 bean 的实例化流程,其中 AbstractAutoProxyCreator 实现了前者:

public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
	Object cacheKey = getCacheKey(beanClass, beanName);

	// 如果其未指定自定义的目标源
	if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
		// 如果已经被代理
		if (this.advisedBeans.containsKey(cacheKey)) {
			return null;
		}
		// 是基础设施类,或者需要跳过
		if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return null;
		}
	}

	// 如果用户指定的自定义的目标源,则尝试获取目标源并根据其创建代理
	// 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.
	TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
	if (targetSource != null) {
		if (StringUtils.hasLength(beanName)) {
			this.targetSourcedBeans.add(beanName);
		}
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
		Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
		this.proxyTypes.put(cacheKey, proxy.getClass());
		return proxy;
	}

	return null;
}

protected Object getCacheKey(Class<?> beanClass, @Nullable String beanName) {
	// 如果有 beanName,则使用 beanName 作为 key
	if (StringUtils.hasLength(beanName)) {
		return (FactoryBean.class.isAssignableFrom(beanClass) ?
				BeanFactory.FACTORY_BEAN_PREFIX + beanName : beanName);
	}
	// 否则使用类型作为 key
	else {
		return beanClass;
	}
}

这段代码的作用是在实例化Bean之前进行处理。它检查Bean是否需要被代理:

  • 如果需要,根据自定义目标源创建代理对象,并返回代理对象;
  • 如果不需要代理或者不存在自定义目标源,则直接返回 null,即走正常的 bean 实例化逻辑;

它主要是用来在更灵活的创建代理目标的,一般我们并不会用到,因此这里了解即可。

2、作为早期引用被创建时

SmartInstantiationAwareBeanPostProcessor 提供了三个方法,AbstractAutoProxyCreator 实现了两个:

  • predictBeanType :确认 bean 的类型,这里会直接获取代理对象的类型;
  • getEarlyBeanReference :获取对象早期引用,这里会通过 wrapIfNecessary 尝试为 bean 创建代理对象;

在开始前,我们需要明确,什么是早期引用
一般情况下,Spring 会在 bean 初始化完毕后才会基于该 bean 实例创建代理对象,但是在循环引用时,比如 beanA 依赖 beanB 依赖 beanA 的情况下,由于后创建的 beanB 需要依赖先创建的 beanA,而在此时先创建的 beanA 并未完成初始化,则此时后创建的 beanB 会通过一级缓存中的 ObjectFactory ,也就是 () → getEarlyBeanReference 方法提前获得基于 beanB 创建的代理对象(如果不需要代理则就是 beanA 本身),这就是早期引用。
不过,虽然是早期引用阶段,但是实际上在这里创建代理对象的逻辑是与正常的初始化后创建代理对象的逻辑基本一致的:

public Object getEarlyBeanReference(Object bean, String beanName) {
	Object cacheKey = getCacheKey(bean.getClass(), beanName);
	this.earlyProxyReferences.put(cacheKey, bean);
	return wrapIfNecessary(bean, beanName, cacheKey);
}

后文我们需要重点关注 wrapIfNecessary 方法,不过目前我们知道在这一步会创建代理对象即可。

3、在初始化阶段

SmartInstantiationAwareBeanPostProcessor 提供了两个方法,AbstractAutoProxyCreator 只实现了其中的 postProcessBeforeInstantiation ,在初始化前,它将为 bean 生成代理对象:

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

getEarlyBeanReference 基本一致,都是基于 wrapIfNecessary 完成的,只不过是时机不同。正常需要代理的 bean 会在这里被替换为代理对象。

二、创建代理对象前的准备

知道了代理对象在何时被创建,也大概了解了相关的基本组件,现在我们需要真正的了解代理对象是如何被创建的,通知、切点和通知器这些组件将会在这个过程中扮演怎样的角色。
wrapIfNecessary 方法则是入口,在这个方法中,spring 会确认 bean 是否需要被代理,如果是就为其创建代理对象:

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
	// 指定的目标源的对象不需要再代理(因为在初始化阶段就处理完了)
	if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
		return bean;
	}
	// 已经被代理则不需要再代理
	if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
		return bean;
	}
	// 如果是基础设施类,或者需要跳过就不代理
	if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}

	// 为 bean 获取需要的通知器
	// Create proxy if we have advice.
	Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
	if (specificInterceptors != DO_NOT_PROXY) {
		// 注明该 bean 已经被代理
		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;
}

1、为 bean 获取通知器

当获得一个 bean 时,spring 会通过 getAdvicesAndAdvisorsForBean 方法为这个 bean 获得它需要的通知器与通知,在 AbstractAutoProxyCreator 它是个空实现,AbstractAdvisorAutoProxyCreator 实现了

@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(
		Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {

	// 查找符合条件的通知器
	List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
	if (advisors.isEmpty()) {
		return DO_NOT_PROXY;
	}
	return advisors.toArray();
}

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
	// 获取 spring 容器中所有的 Advisor
	List<Advisor> candidateAdvisors = findCandidateAdvisors();
	List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
	extendAdvisors(eligibleAdvisors);
	if (!eligibleAdvisors.isEmpty()) {
		eligibleAdvisors = sortAdvisors(eligibleAdvisors);
	}
	return eligibleAdvisors;
}

// 获取 spring 容器中所有的 Advisor
// 就是字面意思,从 BeanFactory 中实例化所有 Advisor 并返回
protected List<Advisor> findCandidateAdvisors() {
	Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
	return this.advisorRetrievalHelper.findAdvisorBeans();
}

protected List<Advisor> findAdvisorsThatCanApply(
		List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {

	// 一个类似 TransactionSynchronizationManager 的上下文,用于记录当前正在创建代理对象的 bean 的一些信息
	ProxyCreationContext.setCurrentProxiedBeanName(beanName);
	try {
		return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
	}
	finally {
		// 将其从上下文中移除
		ProxyCreationContext.setCurrentProxiedBeanName(null);
	}
}

整体逻辑比较直观,总共就三步:

  • BeanFactory 加载并获取所有的 Advisor
  • 从这些 Advisor 中筛选出 bean 需要的部分;
  • 将这些 Advisor@Order 或者 Ordered 接口排序;

值得一提的是,在 AnnotationAwareAspectJAutoProxyCreator 中,它对 findCandidateAdvisors 进行了重写,在原有逻辑的基础上添加了基于 AspectJ 生成的 Advisor ,这里暂且先知道即可。

2、筛选匹配通知器

这里我们额外的看一下 AopUtils.findAdvisorsThatCanApply 方法,它揭露了通知器 Advisor 是如何判断是否需要为这个 bean 应用切点的:

public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
	if (candidateAdvisors.isEmpty()) {
		return candidateAdvisors;
	}
	List<Advisor> eligibleAdvisors = new ArrayList<>();
	for (Advisor candidate : candidateAdvisors) {
		// 如果是针对类型匹配
		if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
			eligibleAdvisors.add(candidate);
		}
	}
	boolean hasIntroductions = !eligibleAdvisors.isEmpty();
	for (Advisor candidate : candidateAdvisors) {
		if (candidate instanceof IntroductionAdvisor) {
			// already processed
			continue;
		}
		if (canApply(candidate, clazz, hasIntroductions)) {
			eligibleAdvisors.add(candidate);
		}
	}
	return eligibleAdvisors;
}

public static boolean canApply(Advisor advisor, Class<?> targetClass) {
	return canApply(advisor, targetClass, false);
}

public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
	// 如果针对类型拦截
	if (advisor instanceof IntroductionAdvisor) {
		return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
	}
	// 如果针对方法拦截
	else if (advisor instanceof PointcutAdvisor pca) {
		return canApply(pca.getPointcut(), targetClass, hasIntroductions);
	}
	else {
		// It doesn't have a pointcut so we assume it applies.
		return true;
	}

public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
	Assert.notNull(pc, "Pointcut must not be null");
	if (!pc.getClassFilter().matches(targetClass)) {
		return false;
	}

	// 获取方法匹配器
	MethodMatcher methodMatcher = pc.getMethodMatcher();
	if (methodMatcher == MethodMatcher.TRUE) {
		// No need to iterate the methods if we're matching any method anyway...
		return true;
	}

	// 如果可以同时针对方法和类型匹配
	IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
	if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
		introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
	}

	Set<Class<?>> classes = new LinkedHashSet<>();
	if (!Proxy.isProxyClass(targetClass)) {
		classes.add(ClassUtils.getUserClass(targetClass));
	}
	classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));

	for (Class<?> clazz : classes) {
		// 获取这个 bean 中直接声明的方法
		Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
		for (Method method : methods) {
			// 根据方法、或者同时根据方法与类型判断是否要应用通知
			if (introductionAwareMethodMatcher != null ?
					introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
					methodMatcher.matches(method, targetClass)) {
				return true;
			}
		}
	}

	return false;
}

这里大体处理了两类匹配逻辑:

  • 如果通知器是 IntroductionAdvisor  类型,则通过通知器的 ClassFilter 进行类型匹配;
  • 如果通知器是 PointcutAdvisor  类型,则通过通知器的 Pointcut 切点中的 ClassFilterMethodMatcher 分别对类型和类中的方法进行匹配。不过,针对 MethodMatcher 又分两种情况:
    1. MethodMatcherIntroductionAwareMethodMatcher  类型,说明支持同时根据方法和 bean 的类型进行匹配;
    2. 如果不是,则说明只支持根据方法进行匹配;

3、确认代理类型

让我们回到 wrapIfNecessary ,现在我们得到了所有可以作用于 bean 上的 Advisor ,接下来就需要根据这些 Advisor 去创建代理对象:

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		// ... ...

		// 获取可作用于 bean 的 Advisor
		// 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;
	}

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

	// 根据 ProxyConfig(就是 AbstractAutoProxyCreator 本身)创建代理工厂
	ProxyFactory proxyFactory = new ProxyFactory();
	proxyFactory.copyFrom(this);

	// 如果需要基于目标类而不是其接口代理(即这个代理类没实现接口)
	// 并且他们已经被 jdk 代理了(比如 Annotation 或者 Mybatis 的 Mapper),或者是根据 lambda 生成的匿名内部类
	// 那么生成的代理类需要实现这些接口类型
	if (proxyFactory.isProxyTargetClass()) {
		// Explicit handling of JDK proxy targets and lambdas (for introduction advice scenarios)
		if (Proxy.isProxyClass(beanClass) || ClassUtils.isLambdaClass(beanClass)) {
			// Must allow for introductions; can't just set interfaces to the proxy's interfaces only.
			for (Class<?> ifc : beanClass.getInterfaces()) {
				proxyFactory.addInterface(ifc);
			}
		}
	}
	// 其他情况下,根据 beanDefinition 中的 preserveTargetClass 属性
	// 判断是否要直接基于这个类而不是其接口创建代理对象,简而言之,就是要不要走 CGLib 代理
	else {
		// No proxyTargetClass flag enforced, let's apply our default checks...
		if (shouldProxyTargetClass(beanClass, beanName)) {
			proxyFactory.setProxyTargetClass(true);
		}
		// 否则直接从这个类实现的接口中寻找可以用于代理的接口
		else {
			evaluateProxyInterfaces(beanClass, proxyFactory);
		}
	}

	// 创建 Advisor 
	// 一般情况下,这里就是各种 Advisor,不过也可能混有用于支持 AspectJ 的特殊对象,因此需要在这里统一处理
	// 转为 Advisor 
	Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
	proxyFactory.addAdvisors(advisors);
	proxyFactory.setTargetSource(targetSource);
	customizeProxyFactory(proxyFactory);

	// 是否要启用 advisor 的预过滤,在 AbstractAutoProxyCreator 中总是返回 false
	// 因此我们可以认为总是为 true
	proxyFactory.setFrozen(this.freezeProxy);
	if (advisorsPreFiltered()) {
		proxyFactory.setPreFiltered(true);
	}

	// 获取类加载器,然后创建代理对象
	// Use original ClassLoader if bean class not locally loaded in overriding class loader
	ClassLoader classLoader = getProxyClassLoader();
	if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) {
		classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();
	}
	return proxyFactory.getProxy(classLoader);
}

protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) {
	Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader());
	boolean hasReasonableProxyInterface = false;
	for (Class<?> ifc : targetInterfaces) {
		// 确认接口是否满足下列条件,如果是那就使用它作为代理接口:
		// 1、是否不为 Aware 这样的 Spring 回调接口
		// 2、是否不为 cglib.proxy.Factory 这样的内部接口
		// 3、是否有定义抽象方法(如果没有抽象方法那自然也没必要代理了)
		if (!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) &&
				ifc.getMethods().length > 0) {
			hasReasonableProxyInterface = true;
			break;
		}
	}
	// 如果找到了代理接口,说明需要基于接口代理
	// 那就让代理对象实现所有的接口
	if (hasReasonableProxyInterface) {
		// Must allow for introductions; can't just set interfaces to the target's interfaces only.
		for (Class<?> ifc : targetInterfaces) {
			proxyFactory.addInterface(ifc);
		}
	}
	// 如果没有找到代理接口,那就让他基于对象本身的类型生成代理
	else {
		proxyFactory.setProxyTargetClass(true);
	}
}

暂且忽略代理工厂 ProxyFactory 中的逻辑,这里主要做了这么个判断:

  1. 如果 proxyFactory 设置了 proxyTargetClass 标志为 true,则说明要使用目标类(target class)作为代理的基础。在这种情况下,如果目标类是JDK动态代理的代理类或者是 Lambda 表达式生成的匿名内部类,则需要特殊处理,即通过遍历目标类的接口,将这些接口添加到代理工厂中,以保证代理对象具备这些接口的方法;
  2. 如果 proxyFactoryproxyTargetClass 标志没有设置为 true,则执行下面的逻辑。这表示没有显式要求使用目标类作为代理基础,并且可以根据一些默认规则进行判断:
    a. 如果根据默认规则确定应该使用目标类作为代理基础,则将 proxyTargetClass 标志设置为 true ,即需要进行 CGLib 代理;
    b. 如果不满足使用目标类作为代理基础的条件,则根据目标类的接口情况来设置代理工厂的接口。通过调用 evaluateProxyInterfaces(beanClass, proxyFactory) 方法,根据目标类的接口信息,将适合的接口添加到代理工厂中;

4、适配通知器

另外,在 createProxy 中,会调用 buildAdvisors 去适配通知器,这是虽然一般情况下输入的 specificInterceptors 大部分都是 Advisor ,不过也可能有一些其他的类型需要特殊处理,比如大家都很熟悉的 MethodInterceptor,它只实现了 Advice 接口,因此需要在这里被适配为 DefaultPointcutAdvisor
总而言之,在创建代理对象前,需要调用适配器将里面入参的 Object 类型的数组 specificInterceptors ,全部确保转为 Advisor

protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
	// 有些拦截器是直接通过把 beanName 设置到 AbstractAutoProxyCreator 注册的
	// 因此此处需要将他们直接取出来
	// Handle prototypes correctly...
	Advisor[] commonInterceptors = resolveInterceptorNames();

	// 收集所有可用的拦截器
	List<Object> allInterceptors = new ArrayList<>();
	if (specificInterceptors != null) {
		if (specificInterceptors.length > 0) {
			// specificInterceptors may equal PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS
			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.isTraceEnabled()) {
		int nrOfCommonInterceptors = commonInterceptors.length;
		int nrOfSpecificInterceptors = (specificInterceptors != null ? specificInterceptors.length : 0);
		logger.trace("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors +
				" common interceptors and " + nrOfSpecificInterceptors + " specific interceptors");
	}
	
	// 调用通知器适配器注册表 advisorAdapterRegistry,尝试将所有的拦截器对象适配为通知器
	Advisor[] advisors = new Advisor[allInterceptors.size()];
	for (int i = 0; i < allInterceptors.size(); i++) {
		advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
	}
	return advisors;
}

private Advisor[] resolveInterceptorNames() {
	BeanFactory bf = this.beanFactory;
	ConfigurableBeanFactory cbf = (bf instanceof ConfigurableBeanFactory ? (ConfigurableBeanFactory) bf : null);
	List<Advisor> advisors = new ArrayList<>();
	for (String beanName : this.interceptorNames) {
		if (cbf == null || !cbf.isCurrentlyInCreation(beanName)) {
			Assert.state(bf != null, "BeanFactory required for resolving interceptor names");
			Object next = bf.getBean(beanName);
			advisors.add(this.advisorAdapterRegistry.wrap(next));
		}
	}
	return advisors.toArray(new Advisor[0]);
}

这里我们需要看一下 AdvisorAdapterRegistry 的唯一一个实现类 DefaultAdvisorAdapterRegistrywrap 方法:

@Override
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
	// 已经是 Advisor 了,直接返回
	if (adviceObject instanceof Advisor) {
		return (Advisor) adviceObject;
	}
	// 没有实现 Advice 接口,直接抛异常
	if (!(adviceObject instanceof Advice advice)) {
		throw new UnknownAdviceTypeException(adviceObject);
	}
	// 是方法拦截器,这是最常见的实现
	if (advice instanceof MethodInterceptor) {
		// So well-known it doesn't even need an adapter.
		return new DefaultPointcutAdvisor(advice);
	}
	// 不是上述两者,则调用 AdvisorAdapter 链尝试将其适配为 Advisor 
	for (AdvisorAdapter adapter : this.adapters) {
		// Check that it is supported.
		if (adapter.supportsAdvice(advice)) {
			return new DefaultPointcutAdvisor(advice);
		}
	}
	throw new UnknownAdviceTypeException(advice);
}

这里的逻辑还是比较直白的:

  • 如果已经是 Advisor 了,就直接返回;
  • 如果不是 Advisor ,那必须是 Advice ,否则直接抛异常;
  • 如果它是 MethodInterceptor ,那就将其适配为 DefaultPointcutAdvisor (可能是考虑到 spring 中几乎九成九的 AOP 都是基于 MethodInterceptor 实现的,因此这里直接专门提出来了);
  • 如果是其他情况,就调用适配器链,找到一个支持处理这个拦截器的 AdvisorAdapter 去对它做适配;

三、创建代理对象

经历了一番波折,现在我们得到了所有最终可用的 Advisor ,以及在 ProxyFactory 设置好了代理类要实现哪些类型,现在我们看看 ProxyFactory.getProxy 是如何创建代理对象的:

public Object getProxy(@Nullable ClassLoader classLoader) {
	return createAopProxy().getProxy(classLoader);
}

protected final synchronized AopProxy createAopProxy() {
		if (!this.active) {
			activate();
		}
		// 获取 AOP 代理工厂,默认为 DefaultAopProxyFactory
		return getAopProxyFactory()
			.createAopProxy(this);
	}

1、确认代理方式

在默认情况下,getAopProxyFactory 会获得一个 DefaultAopProxyFactory 实例,在 createAopProxy 方法中,会根据各种条件决定要使用何种方式生成代理:

public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {

	private static final long serialVersionUID = 7930414337282325166L;

	@Override
	public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
		if (!NativeDetector.inNativeImage() &&
				(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 代理:
			// 1、代理的目标类是接口;
			// 2、代理的目标类本身就是个代理类
			// 3、代理的目标类是基于 Lambda 表达式生成的匿名内部类
			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass) || ClassUtils.isLambdaClass(targetClass)) {
				return new JdkDynamicAopProxy(config);
			}

			// 否则基于 Cglib 代理
			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])));
	}

}

这里主要做了这三层判断:

  1. 如果应用程序运行在 Native Image环境中(即原生镜像化环境,例如 GraalVM 的 Native Image 模式),则直接返回使用JDK动态代理 JdkDynamicAopProxy
  2. 如果配置中设置了优化标志 optimize,或者配置中设置了 proxyTargetClass 标志,或者没有提供用户自定义的代理接口(即没有明确指定要代理的接口),则需要进一步判断:
    a. 如果目标类 targetClass 为空,则抛出 AopConfigException 异常,提示无法确定目标类;
    b. 如果目标类是接口类型 targetClass.isInterface(),或者是JDK动态代理的代理类 Proxy.isProxyClass(targetClass),或者是Lambda表达式生成的类 ClassUtils.isLambdaClass(targetClass),则返回使用JDK动态代理;
    c. 如果以上条件都不满足,即目标类既不是接口也不是代理类,那么返回使用CGLIB动态代理 ObjenesisCglibAopProxy
  3. 如果以上条件都不满足,则默认使用JDK动态代理 JdkDynamicAopProxy

简而言之,仅当代理的目标类没有接口,且不是代理类的时候,才会使用 Cglib 基于子类生成代理对象,这也是为什么即使我们的 bean 没有实现任何接口,Spring 依然能够生成代理的原因。

2、创建代理类

现在,通过 ProxyFactory 中的 AopProxyFactory ,我们可能获得 JdkDynamicAopProxy 或者 ObjenesisCglibAopProxy 对象,我们以比较常见的 JdkDynamicAopProxy 为例,看看它是如何真正的创建代理对象的:

@Override
	public Object getProxy(@Nullable ClassLoader classLoader) {
		if (logger.isTraceEnabled()) {
			logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
		}
		return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
	}

这里平平无奇的直接调用了 Proxy.newProxyInstance ,那么显然一切的奥秘都在最后作为 InvocationHandler 传入的这个 this ,也就是 JdkDynamicAopProxy 本身。
先看看它的成员变量和构造函数:

final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {

	// 代理对象的生成配置,即 AbstractAutoProxyCreator 本身
	// 此处保存有该 bean 的 Advisor 与代理方法的映射关系,以及该代理对象实现的接口类型
	// 本身也是一个 Advised,当我通过代理对象调用 Advised 接口中声明的方法时,都会转发到这里
	private final AdvisedSupport advised;
	
	// 代理对象要实现哪些接口
	private final Class<?>[] proxiedInterfaces;

	// 是否有重写 hashCode 或者 equals 方法
	private boolean equalsDefined;
	private boolean hashCodeDefined;

	/**
	 * Construct a new JdkDynamicAopProxy for the given AOP configuration.
	 * @param config the AOP configuration as AdvisedSupport object
	 * @throws AopConfigException if the config is invalid. We try to throw an informative
	 * exception in this case, rather than let a mysterious failure happen later.
	 */
	public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
		Assert.notNull(config, "AdvisedSupport must not be null");
		if (config.getAdvisorCount() == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
			throw new AopConfigException("No advisors and no TargetSource specified");
		}
		this.advised = config;
		// 确认是否有重新 hashCode 或者 equals 放方法
		this.proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
		findDefinedEqualsAndHashCodeMethods(this.proxiedInterfaces);
	}
}

在创建代理前,它会先添加一些默认的接口:

static Class<?>[] completeProxiedInterfaces(AdvisedSupport advised, boolean decoratingProxy) {
	Class<?>[] specifiedInterfaces = advised.getProxiedInterfaces();
	if (specifiedInterfaces.length == 0) {
		// No user-specified interfaces: check whether target class is an interface.
		Class<?> targetClass = advised.getTargetClass();
		if (targetClass != null) {
			if (targetClass.isInterface()) {
				advised.setInterfaces(targetClass);
			}
			else if (Proxy.isProxyClass(targetClass) || ClassUtils.isLambdaClass(targetClass)) {
				advised.setInterfaces(targetClass.getInterfaces());
			}
			specifiedInterfaces = advised.getProxiedInterfaces();
		}
	}

	// 添加 SpringProxy、Advised 接口
	List<Class<?>> proxiedInterfaces = new ArrayList<>(specifiedInterfaces.length + 3);
	for (Class<?> ifc : specifiedInterfaces) {
		// Only non-sealed interfaces are actually eligible for JDK proxying (on JDK 17)
		if (!ifc.isSealed()) {
			proxiedInterfaces.add(ifc);
		}
	}
	if (!advised.isInterfaceProxied(SpringProxy.class)) {
		proxiedInterfaces.add(SpringProxy.class);
	}
	if (!advised.isOpaque() && !advised.isInterfaceProxied(Advised.class)) {
		proxiedInterfaces.add(Advised.class);
	}
	// 如果通知器 DecoratingProxy,就让代理对象也实现 DecoratingProxy
	if (decoratingProxy && !advised.isInterfaceProxied(DecoratingProxy.class)) {
		proxiedInterfaces.add(DecoratingProxy.class);
	}
	return ClassUtils.toClassArray(proxiedInterfaces);
}

3、代理方法

InvocationHandler.invoke 是代理对象拦截待执行方法的关键,在 JdkDynamicAopProxy 中,它区分了五类方法,并做了不同的处理,这里我们主要关注后续通过 getInterceptorsAndDynamicInterceptionAdvice 获取通知调用链的部分:

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 {
		// 调用 eqlues 方法
		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();
		}
		// 如果调用的方法来自于 DecoratingProxy 接口
		else if (method.getDeclaringClass() == DecoratingProxy.class) {
			// There is only getDecoratedClass() declared -> dispatch to proxy config.
			return AopProxyUtils.ultimateTargetClass(this.advised);
		}
		// 如果这个方法来自于 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);
		}

		// 真正的调用的进行增强,即调用 AOP 植入的各种前置和后置放阿飞
		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.
		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;
		}
		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);
		}
	}
}

4、获取拦截器链

通过  AdvisedSupport (其实就是 ProxyFactory)的 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 默认只有 DefaultAdvisorChainFactory 一个实现类,因此我们直接看它的 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) {

		// 1、如果基于方法切点拦截,则根据方法切点判断通知是否生效
		if (advisor instanceof PointcutAdvisor pointcutAdvisor) {

			// 由于 isPreFiltered 必定为 true,因此这里实际上就是看看方法切点是否支持处理这个类型的 bean
			// Add it conditionally.
			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);
					// 如果这个方法检查器是动态的,即每次调用的时候才检查是否生效,那就将其包装为 InterceptorAndDynamicMethodMatcher
					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));
					}
				}
			}
		}

		// /2、如果基于类拦截,则基于类确认该通知是否生效
		else if (advisor instanceof IntroductionAdvisor ia) {
			if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
				Interceptor[] interceptors = registry.getInterceptors(advisor);
				interceptorList.addAll(Arrays.asList(interceptors));
			}
		}

		// 3、其他的情况,比如基于 AspectJ,直接将其包装为 MethodInterceptor
		else {
			Interceptor[] interceptors = registry.getInterceptors(advisor);
			interceptorList.addAll(Arrays.asList(interceptors));
		}
	}

	return interceptorList;
}

可以看到,这里主要是检查将各种不同类型的 Advisor 是否支持处理该类型的 bean,如果是,就将其转为 MethodInterceptor ,然后收集所有的拦截器凑成链后,返回给代理对象:

  • 如果当前的 Advisor 是一个 PointcutAdvisor,即基于切点的通知器,那么:
    1. 先根据切点的 ClassFilter 判断是否匹配成功,然后再根据节点的 MethodMatcher 的类型,觉得要根据方法还是同时根据方法与类进行匹配;
    2. 如果匹配成功,再判断 MethodMatcher 是否根据方法调用情况动态的决定是否匹配,若是则将其包装为 InterceptorAndDynamicMethodMatcher 并添加到拦截器链;
  • 如果当前的 Advisor 是一个IntroductionAdvisor,即引介增强器,那么根据类过滤器的匹配规则判断是否需要将它添加到拦截器链中;
  • 如果当前的 Advisor 不是上述两种类型,直接将它的拦截器数组添加到拦截器链中;

5、执行拦截器链

回到 invoke 方法,现在我们通过 getInterceptorsAndDynamicInterceptionAdvice 方法获取调用链后,就该真正的执行它的:

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		
		// ... ...

		// 真正的调用的进行增强,即调用 AOP 植入的各种前置和后置放阿飞
		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.
		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();
		}

		// ... ...
}

执行上下文

其中,ReflectiveMethodInvocation 是一个包含了本次调用信息的一个执行上下文,它将在拦截器链中流转以完成全部的流程:

public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable {

	// 代理对象
	protected final Object proxy;

	// 原始对象与代理的方法
	@Nullable
	protected final Object target;
	protected final Method method;

	// 本次调用的参数
	protected Object[] arguments;
	// 调用对象的类型
	@Nullable
	private final Class<?> targetClass;

	// 一些特殊的参数
	@Nullable
	private Map<String, Object> userAttributes;

	// 拦截器链
	protected final List<?> interceptorsAndDynamicMethodMatchers;

	// 当前调用的拦截器链的下标
	private int currentInterceptorIndex = -1;

	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; // 拦截器链
	}
}

调用拦截器链

当我们调用 ReflectiveMethodInvocation.proceed 方法的时候,实际上是会先调用拦截器链:

public Object proceed() throws Throwable {
	// 如果没有拦截器,直接调用方法本身
	// We start with an index of -1 and increment early.
	if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
		return invokeJoinpoint();
	}
	
	// 获取拦截器,并让 currentInterceptorIndex + 1
	Object interceptorOrInterceptionAdvice =
			this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);

	// 如果是动态拦截器,就根据当前的调用参数判断是否要应用它
	if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher dm) {
		// Evaluate dynamic method matcher here: static part will already have
		// been evaluated and found to match.
		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.
		return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
	}
}

protected Object invokeJoinpoint() throws Throwable {
	return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);
}

这个地方稍微有点绕,大概意思是这样的:

  • 首先,ReflectiveMethodInvocation 在内部维护了一个成员变量 currentInterceptorIndex ,代表了当前调用到第几个拦截器;
  • 每当调用了一个拦截器后,都会使 currentInterceptorIndex 加一,也就是说,每当调用一次 proceed 方法,都相当于执行了一个拦截器;
  • currentInterceptorIndex 等于拦截器链的长度减一时,意味着所有的拦截器都调用完毕,此时真正的调用被拦截的方法;

在这个基础上,每次调用拦截器前,都会做一次判断,如果拦截器是动态拦截器,就根据方法参数判断是否要调用它,否则就直接调用 processed 跳过这个拦截器。
这也就意味着,我们在拦截器中完成拦截操作后,是需要主动的调用 ReflectiveMethodInvocation.processed方法的,这个时候就体现出了这种设计的精妙之处:

  • 允许主动中断:只有调用 proceed 时,拦截器链才会继续往下走,否则可以直接中断整个调用流程;
  • 可以拦截调用结果:当调用 proceed 后,实际上会形成递归,这使得所有的拦截器都可以获取并处理方法的返回值;

总结

1、代理的创建时机

  • 实例化前后:依靠 InstantiationAwareBeanPostProcessor 完成,不太常见;
  • 初始化后:依靠 BeanPostProcessor 完成,如果没有因为循环依赖导致 bean 被提前实例化,那么正常情况 bean 会在这时被代理;
  • 获取早期引用时:依靠 SmartInstantiationAwareBeanPostProcessor 完成,当需要被代理的 bean 由于循环依赖导致初始化前就要被其他 bean 获取时,会在这时被提前完成代理;

其中,后两者最终都会通过 AbstractAutoProxyCreator.wrapIfNecessary 完成代理对象的创建。

2、通知器的获取

当进入 wrapIfNecessary 方法后,在真正的创建代理对象前,需要通过AbstractAutoProxyCreator.getAdvicesAndAdvisorsForBean 方法获取可应用于代理对象的通知器。
该方法的具体实现位于 AbstractAdvisorAutoProxyCreator 中:

  • 调用 findEligibleAdvisors 用于查出是否有可用的通知器;
  • findEligibleAdvisors 方法中,通过 findCandidateAdvisors 加载 spring 容器中的所有 Advisor ,在 AnnotationAwareAspectJAutoProxyCreator 中通过重写该方法,额外加载了一些基于 AspectJ 的通知器;
  • 再调用 findAdvisorsThatCanApply 从所有的 Advisor 中筛选出可应用于当前 bean 的通知器:
    1. 如果通知器是 IntroductionAdvisor  类型,则通过通知器的 ClassFilter 进行类型匹配;
    2. 如果通知器是 PointcutAdvisor  类型,则通过通知器的 Pointcut 切点中的 ClassFilterMethodMatcher 分别对类型和类中的方法进行匹配。其中,若 MethodMatcher 类型为 IntroductionAwareMethodMatcher ,则支持同时根据方法与其类型进行匹配;
    3. 如果通知器不是上述两者,则认为其必定可应用与当前 bean;

经过上述流程后若当前 bean 没有任何可用的通知器,则说明其无需代理,否则需要通过通知器进行代理增强。

3、代理前的准备

获得可用的通知器后,将会调用 createProxy 方法真正的进入创建代理对象的逻辑中。

  • 创建一个 ProxyFactory 用于后续创建代理对象;
  • 尝试推断代理对象的类型:
    1. proxyFactory 设置了 proxyTargetClass 标志为 true,则说明要使用目标类(target class)作为代理的基础。在这种情况下,如果目标类是 JDK 动态代理的代理类(比如 Annotation)或者是 Lambda 表达式生成的匿名内部类,则需要遍历目标类的接口,将这些接口添加到代理工厂中,以保证代理对象具备这些接口的方法;
    2. 如果 proxyFactoryproxyTargetClass 标志没有设置为 true,则执行下面的逻辑。这表示没有显式要求使用目标类作为代理基础,则:
      a.应该使用目标类作为代理基础,则将 proxyTargetClass 标志设置为 true ,即需要进行 CGLib 代理;
      b.不满足使用目标类作为代理基础的条件,则调用 evaluateProxyInterfaces 方法,根据目标类的接口信息,将适合的接口添加到代理工厂中;
  • 适配通知器:在这一步,大部分的 Advisor 都以及被搜集到了,不过仍有一些通知器需要在 buildAdvisors 方法中进行适配或者特殊的处理:
    1. 收集通用通知器:处了在容器中注册的通知器外,有另一部分通用通知器直接通过直接在 AbstractAutoProxyCreator 中登记 beanName 的方法设置,此时需要根据 beanName 将其从容器中取出;
    2. 适配通知器:此时,已收集的通知器中混有多种类型的对象,因此需要通过 AdvisorAdapterRegistry.wrap **方法将其中非 Advisor 对象进行适配:
      1. 如果已经是 Advisor 了,就直接返回;
      2. 如果不是 Advisor ,那必须是 Advice ,否则直接抛异常;
      3. 如果它是 MethodInterceptor ,那就将其适配为 DefaultPointcutAdvisor
      4. 如果是其他类型的 Advice ,就调用适配器链,找到一个支持处理这个拦截器的 AdvisorAdapter 去对它做适配;

4、创建代理对象

  • 当在 ProxyFactory 中配置好了代理对象的类型、需要实现的接口类型、需要应用的通知器及其他配置后;
  • ProxyFactory 将会在 createAopProxy 方法中获取一个AopProxyFactory (默认为 DefaultAopProxyFactory);
  • 接着调用 DefaultAopProxyFactorycreateAopProxy 方法,根据情况去创建一个 AopProxy 对象:
    1. 如果需要基于目标类代理,那么就使用 CGLib 代理,返回一个 ObjenesisCglibAopProxy
    2. 如果需要基于接口代理,那么使用 JDK 的动态代理,返回一个 JdkDynamicAopProxy
  • 接着我们调用 AopProxygetProxy 方法,该方法将会真正的创建一个代理对象。

5、方法代理

对于 JDK 动态代理来说,用于生成代理的 InvocationHandler 即为 JdkDynamicAopProxy 本身,当我们调用代理对象的方法时,将会统一经过 invoke 方法。
其中,根据方法类型又分为三种类型:

  • equalshashCode 方法:若两方法没有在接口中重新定义,则直接按 JdkDynamicAopProxy 去进行比较/获取哈希值;
  • 如果方法是 DecoratingProxyAdvised 接口中声明的方法,则直接通过当前代理对象内部持有的相应实例进行调用;
  • 如果是普通方法,则在调用前后一次调用通知器中的 Advice 增强逻辑;

其中,对于普通方法,在首次调用 invoke 的时候,将会:

  • 通过内部持有的 AdvisedSupport 对象(即 Advised 的默认实现)的 getInterceptorsAndDynamicInterceptionAdvice 方法获取相应的方法拦截器;
  • 然后 AdvisedSupport 将会通过内部的 AdvisorChainFactory (默认为 DefaultAdvisorChainFactory)的 getInterceptorsAndDynamicInterceptionAdvice 方法创建方法拦截器链;
  • DefaultAdvisorChainFactory 中,将会:
    1. 先取出 AdvisedSupport 中存放的所有可应用于当前 bean 的通知器,然后遍历它们:
      1. 如果当前的 Advisor 是一个 PointcutAdvisor,即基于切点的通知器,那么根据其持有的切点 Pointcut 中的 ClassFilterMethodMatcher 进行匹配;
      2. 如果当前的 Advisor 是一个IntroductionAdvisor,即引介增强器,那么根据类过滤器的匹配规则判断是否需要将它添加到拦截器链中;
      3. 如果当前的 Advisor 不是上述两种类型,直接将它的拦截器数组添加到拦截器链中;
    2. 在获得的可用的通知器后,通过 AdvisorAdapterRegistry.getInterceptors (此处的适配器注册表在上文也用于适配 Advisor)方法将其全部适配为 MethodInterceptor
  • 通过 DefaultAdvisorChainFactory 获取方法拦截器链后,将会将拦截器链与要增强的代理方法封装为一个方法调用对象 MethodInvocation (默认为 ReflectiveMethodInvocation);
  • 然后调用 MethodInvocation.processed 方法,此时将会调用链首的拦截器,接着拦截器再继续调用 processed 方法,递归此步骤,直到整个调用链完成或者中断为止;

标签:拦截器,return,流程,Object,代理,bean,Advisor,AOP,SpringAOP
From: https://www.cnblogs.com/Createsequence/p/18086409

相关文章

  • Spring AOP初探
    SpringAOP初探Springaop,翻译成中文就是面向切面编程;笔者的个人理解是当spring框架执行一系列方法的时候,通过某种机制匹配到各个需要添加额外逻辑的方法也就是执行点,这些执行点类似数学概念中的一个个点,然后一个个点连起来就成为一个平面了;所有的执行点都会被匹配规则匹配到,然......
  • spring refresh的流程(AbstractApplicationContext的refresh方法)
    12个阶段1、prepareRefresh,做准备工作2、obtainFreshBeanFactory,创建或获取beanfactory3、prepareBeanFactory,准备beanfactory4、postProcessBeanFactory,子类扩展beanfactory5、invokeBeanFactoryPostProcessors,后处理器扩展beanfactory6、registerBeanPostProcessors,准备b......
  • 【数据脱敏方案】不使用 AOP + 注解,使用 SpringBoot+YAML 实现
    文章目录引入认识YAML格式规范定义脱敏规则格式脱敏逻辑实现读取YAML配置文件获取脱敏规则通过键路径获取对应字段规则原始优化后对数据进行脱敏处理递归生成字段对应的键路径脱敏测试完整工具类引入在项目中遇到一个需求,需要对交易接口返回结果中的指定字段......
  • AOP
    AOP(AspectOrientedProgramming):动态代理在程序运行期间将某段代码切入到指定方法指定位置进行运行的编程方式。通知方法前置通知:在目标方法运行之前运行后置通知:在目标方法结束之后运行返回通知:在目标方法正常返回之后运行异常通知:在目标方法异常返回之后运行环绕通......
  • 使用AOP记录feign调用日志
    文章目录业务场景使用DemoClientFeignDemlFeignFallBack主要代码DockLogAspectDockLogDockLogServiceDockLogAddDTOJacksonUtils业务场景记录请求第三方接口的情况。@DockLog可以用在类上也可以用在方法上使用DemoClientFeignimportorg.springframework.cloud......
  • 02 JAVA流程控制
    02JAVA流程控制1.用户交互Scannernextline()用的多,next()用的少。nextline()以回车为结束符。也就是说:nextline方法返回的是回车之前的所有字符。可以获得空白。packagecom.mysoft.scanner;importjava.util.Scanner;publicclassDemo02{publicstaticvoidmain......
  • 基于神兔分仓系统的穿透测试流程
    基本信息账户中心地址http://192.168.8.60:30162/center登陆账户信息test654321华泰柜台账户10001437datong888(每次测试配置不同的APPID和AUTHCODE)交易测试下单地址http://192.168.8.60:30722/#/login登陆账号信息10001437datong888服务器IP192.168.1......
  • 100_Windows服务器部署流程
    服务器煤矿IP用户名密码系统内存硬盘集团administratorNhjc1234WinServer201616G1T煤矿端口规划集团端描述端口用户名密码前端80mysql21836root1q2w3e4r!Q@W#E$Rredis22836root1q2w3e4r!Q@W#E$Rminio23836......
  • MapReduce执行流程
    MapReduce执行流程MapTask执行流程Read:读取阶段MapTask会调用InputFormat中的getSplits方法来对文件进行切片切片之后,针对每一个Split,产生一个RecordReader流用于读取数据数据是以Key-Value形式来产生,交给map方法来处理。每一个键值对触发调用一次map方法Map:映射阶......
  • Java-SpringAop 编程式事物实现
    SpringAop编程式事物实现1.数据库事物特性原子性多个数据库操作是不可分割的,只有所有的操作都执行成功,事物才能被提交;只要有一个操作执行失败,那么所有的操作都要回滚,数据库状态必须回复到操作之前的状态一致性事物操作成功后,数据库的状态和业务规则必须一致。例如:从A......