7.Spring揭秘-深入AdvisedSupport

7.Spring揭秘-深入AdvisedSupport

萤火虫 757 2021-10-22
书接上文,咱们说到AdvisedSupport类中的两个疑问点。

AdvisorChainFactory

//生产advosir链的工厂接口
public interface AdvisorChainFactory {

	//用生advisor成一个MethodInterceptor的对象集合组(注意:这里仅仅是一个集合,是用来生成链的材料,并不是链)
	List<Object> getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, @Nullable Class<?> targetClass);

}

本工厂接口就一个方法,将Advised中的Advice根据Method生成对应的Interceptor集合,注解上所说的是MethodInterceptor并不准确。

为啥这么说呢?

1、既然使用泛型,既然是MethodInterceptor集合,何不直接使用MethodInterceptor作为泛型呢,所以这里可以看出来并不简单的同注解所说的一样。

可以看下AdvisorChainFactory的有且仅有的一个默认实现类DefaultAdvisorChainFactory是如何实现的。

DefaultAdvisorChainFactory

//一个简单的为方法生成一个advice链的工厂,并且不做缓存由子类或调用类做缓存
public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializable {

	@Override
	public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
			Advised config, Method method, @Nullable Class<?> targetClass) {

		//为了保证调用顺序需要做处理 introductions需要首先调用
		//AdvisorAdapterRegistry这个工具就是将advisor转换成MethodInterceptor的
		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;

		//通过遍历全部advisors将其进行类型转换为对应的interceptor
		//如果是 PointcutAdvisor这种 	转换为InterceptorAndDynamicMethodMatcher或MethodInterceptor
		//如果是 IntroductionAdvisor 转换为IntroductionInterceptor
		//如果是 Advisor				转换为MethodInterceptor
		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;
	}

	... ...

}

内部主要生产三类interceptor,其实也就是对应了AOP概念中的三种代理类型,普通Advisor就是静态的直接转换成MethodInterceptor,在调用时也不需要判断,而PointcutAdvisor因为有内部有Pointcut所以需要判断isRuntiom方法是否为true因此这里为false则直接生成MethodInterceptor,为true需要判断方法参数,因此只能在运行时才知道所以生成了InterceptorAndDynamicMethodMatcher,而为类增加功能的代理introduction则直接生成IntroductionInteceptor因为这个接口就是MethodItercptor的子接口所以这里就直接添加进集合了。

AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();

在本类中又引出了一个接口AdvisorAdaptorRegistor,本接口就是将Advisor转换为MethodIterceptor。下面来看下本接口。

AdvisorAdaptorRegistor

// Advisor适配器注册表的接口。
//这是一个SPI接口,任何Spring使用者都不能实现。
public interface AdvisorAdapterRegistry {

  // 对advice进行包装返回Advisor 。
  // 默认情况下,至少应支持返回如下几种
	// MethodInterceptor
	// MethodBeforeAdvice
	// AfterReturningAdvice
	// ThrowsAdvice
	Advisor wrap(Object advice) throws UnknownAdviceTypeException;

  //返回一个AOP联盟的MethodInterceptor数组,允许在基于拦截的框架中使用给定的Advisor。
  //如果它是org.springframework.aop.PointcutAdvisor ,则不必担心与Advisor关联的切入点:只需返回一个拦截器即可
	MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException;

	//注册给定的AdvisorAdapter。
	//请注意,没有必要为AOP联盟的e拦截器或Spring咨询注册适配器:它们必须由AdvisorAdapterRegistry实现自动识别。
	void registerAdvisorAdapter(AdvisorAdapter adapter);

}
  • 接口方法将advice包装成Advisor
  • 将Advisor转换为MethodInterceptor[],这里为啥是一个集合呢?因为这个advisor可能匹配多个MethodInterceptor,不过目前还没发现这种。
  • 最重要的一个方法,注册AdvisorAdapter

这个AdvisorAdapter这里我想你应该也知道了,就是把Advisor转为MethodInterceptor

DefaultAdvisorAdapterRegistry
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {

	private final List<AdvisorAdapter> adapters = new ArrayList<>(3);

	public DefaultAdvisorAdapterRegistry() {
		registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
		registerAdvisorAdapter(new AfterReturningAdviceAdapter());
		registerAdvisorAdapter(new ThrowsAdviceAdapter());
	}


	@Override
	public 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) {
			return new DefaultPointcutAdvisor(advice);
		}
		for (AdvisorAdapter adapter : this.adapters) {
			if (adapter.supportsAdvice(advice)) {
				return new DefaultPointcutAdvisor(advice);
			}
		}
		throw new UnknownAdviceTypeException(advice);
	}

	@Override
	public 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[0]);
	}

	@Override
	public void registerAdvisorAdapter(AdvisorAdapter adapter) {
		this.adapters.add(adapter);
	}

}

方法清晰明了我想这里也就不需要在进行细致的讲解了。

那就看看AdvisorAdapter到底是哈?

AdvisorAdapter

public interface AdvisorAdapter {

	boolean supportsAdvice(Advice advice);

	MethodInterceptor getInterceptor(Advisor advisor);

}
  • 判断这个adapter是否支持本advice
  • 在就是转换操作了

本接口有很多实现类,但是内容都是大同小异的,就拿一个来瞅瞅

class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {

	@Override
	public boolean supportsAdvice(Advice advice) {
		return (advice instanceof MethodBeforeAdvice);
	}

	@Override
	public MethodInterceptor getInterceptor(Advisor advisor) {
		MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
		return new MethodBeforeAdviceInterceptor(advice);
	}

}

实现很简单,但是这里又引出了一个东西MethodBeforeAdviceInterceptor类就是MethodInterceptor的子类。那来看看这个子类都干啥了?

MethodBeforeAdviceInterceptor

public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {

	private final MethodBeforeAdvice advice;

	public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
		Assert.notNull(advice, "Advice must not be null");
		this.advice = advice;
	}

	@Override
	public Object invoke(MethodInvocation mi) throws Throwable {
		this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
		return mi.proceed();
	}

}

看invoke方法是不是有点熟悉呢?这是beforAdvice因此需要在方法调用前执行,在看invoke方法,是不是在proceed方法前调用的。

这里放出一个对应的类图。

image-20201220231542574

AOP基础类图

aop基础类图

本类图将上文所提及类根据功能生成一个依赖图。

上文在提及AopProxyFactory的时候只说了AdviseSupoort,并没有说AopProxyFactory如何生成AopProxy,也并没有说AopProxy是干嘛呢的。

接下来就是要细说下AopProxyFactory的独苗实现类,DefaultAopProxyFactory是如何实现的。

DefaultAopProxyFactory

//默认的AopProxyFactory实现类,创建CGLIB代理或JDK动态代理两者之一
//如果AdvisedSupport中条件满足则使用cglib创建代理
// optimize设置为true
// proxyTargetClass设置为true
// 没有指定代理接口,或者被代理的类没有实现接口
//通常proxyTargetClass参数会强制使用cglib代理,或者指定一个或多个接口则使用jdk动态代理
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);
		}
	}

	//确定提供的AdvisedSupport是否仅指定了SpringProxy接口
	private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
		Class<?>[] ifcs = config.getProxiedInterfaces();
		return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
	}

}

其实这里就是判断是使用什么方法生成代理对象

使用Cglib的三个依据

  • optimize设置为true

  • proxyTargetClass设置为true

  • 没有指定代理接口,或者被代理的类没有实现接口

这里并没有什么复杂逻辑。

AopProxy

//用于配置的AOP代理的委托接口,允许创建实际的代理对象。
//如DefaultAopProxyFactory默认的实现可用于JDK动态代理和CGLIB代理
public interface AopProxy {

	Object getProxy();

	Object getProxy(@Nullable ClassLoader classLoader);

}

接口简单,生成代理类,获使用相应classLoader来加载class来生成类。

AopProxy有两个默认实现类,其一是JDKDynamicAopProxy,CglibAopProxy分别对应两种代理生成方式。

既然生成代理对象准备工作已经做完了,接下来就来看看如何生成代理对象的?