02-SpringAop源码分析----核心关键类分析


上篇文章分析了SpringAop核心概念及其含义,从本节开始将剖析SpringAop的底层运行原理,由于篇幅较长会分为多个文章进行输出。本节将详细以Proxy为入口使用SpringAop原生使用方式(不集成Spring)案例对底层原理进行剖析。

SpringAop代理入口

啥是代理入口?

使用过SpringAop框架的小伙伴都知道其底层是使用代理来实现的,SpringAop通过某个类可以生成代理对象,这个类就是代理入口。

SpringAop提供的代理入口

通过翻阅官方文档可以知道SpringAop提供了 : ProxyFactory、ProxyFactoryBean、AspectJProxyFactory这几个入口工厂。根据这些入口可以构建出如下UML图:

  • ProxyFactory : 该入口可以再不依赖SpringIoc的情况下使用,相当于原生方式使用了。
  • ProxyFactoryBean : 该入口适用于集成Spring情况下使用,该工厂依赖BeanFactory.
  • AspectJProxyFactoty : 该入口适用于集成Spring并且使用@Aspect注解方式时使用

本文将以ProxyFactory这个代理入口搭配案例进行剖析,因为这个入口是比较简单(纯粹)的。其他两个接口本质上也是在ProxyFactory这个入口的原理的基础上增加了一些feture, 所以只要搞懂ProxyFactory其他两个理解也非常简单。

SpringAop底层核心关键类剖析

开始剖析原理之前先把一些关键的类搞清楚,这样可以事半功倍。如上面UML所示,和ProxyFactory继承关系有关的类ProxyCreatorSupport、AdvisedSupport、ProxyConfig、Advised。上篇文章已经介绍过Advised了,此处不再赘述。

ProxyConfig

​ 顾名思义这是个和代理配置有关的类,如下图所示是该类的核心源码。可以看出像proxyTargetClass、exposeProxy、frozen这些属性好像在前面的Advised接口中也出现过, 通过翻阅源码实际上这些属性就是对Advisoed中的部分方法的实现,ProxyConfig除了做相关实现还额外提供了几个属性和对属性设置默认值。

​ 使用过SpringAop开发的小伙伴应该对proxyTargetClass、exposeProxy属性非常熟悉,是不是在哪里见过?使用SpringBoot开发时一般都会在主启动类上添加一个@EnableAspectJAutoProxy注解以开启基于AOP注解方式的代理,这个注解就包含这两个属性。当在注解中配置了这两个属性的值时,底层会将注解中属性的值映射到ProxyConfig中的proxyTargetClass、exposeProxy中,只不过映射这一过程是SpringAop帮我们做的。

public class ProxyConfig implements Serializable {
	
	//设置是否使用CGLIB进行代理,默认false
	private boolean proxyTargetClass = false;
	
	//设置是否对通过CGLIB创建的代理应用积极的优化,默认不开启。
	//无论是否开启对JDK代理都没有影响,除非非常了解AOP底层是如何优化的否则不建议开启
	private boolean optimize = false;
	
	//设置代理对象是否不可以直接转为Advised接口类型,默认为false可以转为Advised
	//opaque属性的作用和frozen类似,都是为了对代理对象的保护,禁止修改代理对象。
	boolean opaque = false;
	
	//设置是否暴露代理对象,这里暴露的意思指的是将代理对象放入ThreadLocal中
	//以便可以通过AopContext.currentProxy()随时取到代理对象
	boolean exposeProxy = false;
	
	//设置代理配是否被冻结,默认false。
	//如果被冻结则代理生成后不能再通过Advised接口中的addAdvice、addAdvisor()动态添加配置,会报错。
	//默认false则不冻结配置,说明可以在运行期间动态添加advice或advisor。
	private boolean frozen = false;

	public void copyFrom(ProxyConfig other) {
		Assert.notNull(other, "Other ProxyConfig object must not be null");
		this.proxyTargetClass = other.proxyTargetClass;
		this.optimize = other.optimize;
		this.exposeProxy = other.exposeProxy;
		this.frozen = other.frozen;
		this.opaque = other.opaque;
	}
	
	//省略get/set方法............
}

Advised(AdvisedSupport)

​ 从之前的UML图中可以了解到AdvisedSupport实际上是对Advised接口的实现。通常情况下这个类应该实现Advided接口的所有方法,这边SpringAopAdvised接口中和代理属性相关的几个方法实现放到了ProxyConfig中。又因为AdvisedSupport继承了ProxnConfig,所以也相当于实现了所有实现,只不过把和代理属性相关的方法放到了ProxyConfig,这样做的目的是内聚性更强。

分析AdvisedSupport源码之前,先看下它里面涉及的关键类。

TargetSource

TargetSource接口主要用来获取目标对象(被代理的对象),SpringAop提供了多个实现类。由于这个类比较重要所有后面将另起篇章单独剖析,此处先mark一下它是用来获取目标对象的即可。

MethodCacheKey
public class AdvisedSupport extends ProxyConfig implements Advised {

	.......
	
	
	private static final class MethodCacheKey implements Comparable<MethodCacheKey> {

		private final Method method;

		private final int hashCode;

		public MethodCacheKey(Method method) {
			this.method = method;
			this.hashCode = method.hashCode();
		}

		@Override
		public boolean equals(@Nullable Object other) {
			return (this == other || (other instanceof MethodCacheKey &&
					this.method == ((MethodCacheKey) other).method));
		}
		
		......

		@Override
		public int compareTo(MethodCacheKey other) {
			int result = this.method.getName().compareTo(other.method.getName());
			if (result == 0) {
				result = this.method.toString().compareTo(other.method.toString());
			}
			return result;
		}
	}
}

如上图所示MethodCacheKeyAdvisedSupport中的一个静态内部类,用于对Method封装,使其具备比较功能。AdvisedSupport中使用这个类主要用来缓存一个方法与该方法相关的advisor之前的映射关系。

AdvisedSupport

public class AdvisedSupport extends ProxyConfig implements Advised {

	//提供一个默认的目标对象,默认对象为null
	public static final TargetSource EMPTY_TARGET_SOURCE = EmptyTargetSource.INSTANCE;
	TargetSource targetSource = EMPTY_TARGET_SOURCE;

	//标识当前AdvisedSupport中的Advisor是否已经对特定的目标类进行了过滤,默认false
	private boolean preFiltered = false;

	//此处先mark一下,该接口是用来将advisors属性组装为一条拦截链
	AdvisorChainFactory advisorChainFactory = new DefaultAdvisorChainFactory();

	//缓存每个需要被拦截的方法与advisorChainFactory生成的拦截链的映射关系,用于提高性能避免每次都计算链
	private transient Map<MethodCacheKey, List<Object>> methodCache;

	//指定jdk代理生成的代理对象需要实现的接口,以list中的顺序创建jdk代理
	//jdk代理是基于接口的,这个属性的意义在于可以指定对多个接口进行代理,以便代理对象可以转为不同的接口类型
	private List<Class<?>> interfaces = new ArrayList<>();

	//用于保存所有的Advisor
	private List<Advisor> advisors = new ArrayList<>();

	//用数组的形式保存Advisor,和上面的advisor属性同步
	private Advisor[] advisorArray = new Advisor[0];

	public AdvisedSupport() {
		this.methodCache = new ConcurrentHashMap<>(32);
	}

	public AdvisedSupport(Class<?>... interfaces) {
		this();
		setInterfaces(interfaces);
	}

	//设置目标对象,这边使用SingletonTargetSource包装了一下
	public void setTarget(Object target) {
		setTargetSource(new SingletonTargetSource(target));
	}

	@Override
	public void setTargetSource(@Nullable TargetSource targetSource) {
		this.targetSource = (targetSource != null ? targetSource : EMPTY_TARGET_SOURCE);
	}
	
	public void setTargetClass(@Nullable Class<?> targetClass) {
		this.targetSource = EmptyTargetSource.forClass(targetClass);
	}

	//指定AdvisorChainFactory
	public void setAdvisorChainFactory(AdvisorChainFactory advisorChainFactory) {
		Assert.notNull(advisorChainFactory, "AdvisorChainFactory must not be null");
		this.advisorChainFactory = advisorChainFactory;
	}

	//设置jdk代理对象需要代理的接口
	public void setInterfaces(Class<?>... interfaces) {
		Assert.notNull(interfaces, "Interfaces must not be null");
		this.interfaces.clear();
		for (Class<?> ifc : interfaces) {
			addInterface(ifc);
		}
	}

	//添加需要代理的接口,和上面setInterfaces方法的区别是该方法会同步清除methodCache中的缓存
	public void addInterface(Class<?> intf) {
		Assert.notNull(intf, "Interface must not be null");
		if (!intf.isInterface()) {
			throw new IllegalArgumentException("[" + intf.getName() + "] is not an interface");
		}
		if (!this.interfaces.contains(intf)) {
			this.interfaces.add(intf);
			adviceChanged();
		}
	}

	public boolean removeInterface(Class<?> intf) {
		return this.interfaces.remove(intf);
	}

	//获取所有的jdk代理的接口
	@Override
	public Class<?>[] getProxiedInterfaces() {
		return ClassUtils.toClassArray(this.interfaces);
	}
	
	//判断某个是否属于代理接口类型
	@Override
	public boolean isInterfaceProxied(Class<?> intf) {
		for (Class<?> proxyIntf : this.interfaces) {
			if (intf.isAssignableFrom(proxyIntf)) {
				return true;
			}
		}
		return false;
	}
	
	//添加Advisor
	@Override
	public void addAdvisor(Advisor advisor) {
		int pos = this.advisors.size();
		addAdvisor(pos, advisor);
	}
	
	//向advisors中的指定位置添加Advisor
	@Override
	public void addAdvisor(int pos, Advisor advisor) throws AopConfigException {
		if (advisor instanceof IntroductionAdvisor) {
			validateIntroductionAdvisor((IntroductionAdvisor) advisor);
		}
		addAdvisorInternal(pos, advisor);
	}
	
	private void addAdvisorInternal(int pos, Advisor advisor) throws AopConfigException {
		Assert.notNull(advisor, "Advisor must not be null");
		//这边的逻辑就体现了上面ProxyConfig中frozen属性
		//如果frozen属性为true,则advisors会被锁定,不能再动态添加Advisor,否则会直接抛异常
		if (isFrozen()) {
			throw new AopConfigException("Cannot add advisor: Configuration is frozen.");
		}
		if (pos > this.advisors.size()) {
			throw new IllegalArgumentException(
					"Illegal position " + pos + " in advisor list with size " + this.advisors.size());
		}
		this.advisors.add(pos, advisor);
		updateAdvisorArray();
		adviceChanged();
	}
	
	
	@Override
	public boolean removeAdvisor(Advisor advisor) {
		int index = indexOf(advisor);
		if (index == -1) {
			return false;
		}
		else {
			removeAdvisor(index);
			return true;
		}
	}

	@Override
	public boolean replaceAdvisor(Advisor a, Advisor b) throws AopConfigException {
		Assert.notNull(a, "Advisor a must not be null");
		Assert.notNull(b, "Advisor b must not be null");
		int index = indexOf(a);
		if (index == -1) {
			return false;
		}
		removeAdvisor(index);
		addAdvisor(index, b);
		return true;
	}


	private void validateIntroductionAdvisor(IntroductionAdvisor advisor) {
		advisor.validateInterfaces();
		Class<?>[] ifcs = advisor.getInterfaces();
		for (Class<?> ifc : ifcs) {
			addInterface(ifc);
		}
	}
	
	//将advisors中的数据转为数组形式到advisorArray
	protected final void updateAdvisorArray() {
		this.advisorArray = this.advisors.toArray(new Advisor[0]);
	}

	//添加Advice
	@Override
	public void addAdvice(Advice advice) throws AopConfigException {
		int pos = this.advisors.size();
		addAdvice(pos, advice);
	}
	
	//向指定下标添加Advice
	//你可能会好奇,明明AdvisedSupport中没有保存Advice的地方为什么还有这个方法呢?
	@Override
	public void addAdvice(int pos, Advice advice) throws AopConfigException {
		Assert.notNull(advice, "Advice must not be null");
		if (advice instanceof IntroductionInfo) {
			addAdvisor(pos, new DefaultIntroductionAdvisor(advice, (IntroductionInfo) advice));
		}
		else if (advice instanceof DynamicIntroductionAdvice) {
			throw new AopConfigException("DynamicIntroductionAdvice may only be added as part of IntroductionAdvisor");
		}
		else {
			//这边将Advice包装为DefaultPointcutAdvisor,进而可以保存到advisors中
			addAdvisor(pos, new DefaultPointcutAdvisor(advice));
		}
	}

	//缓存获取当前类中的指定方法对应的拦截链
	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;
	}
	
	protected void adviceChanged() {
		this.methodCache.clear();
	}
	
	.............
}

如上所示是AdvisedSupport的核心源码,从中可以看它有如下几个核心功能:

  • 维护用户添加的Advisor(用户添加的Advice最终也会被包装为AdvisorDefaultPointcutAdvisor))
  • 根据List<Advisor> advisor属性中各个Advisor的切点为被代理对象的方法创建对应的拦截链,并且将方法与拦截链的映射关系维护到methodCache属性中缓存起来

维护Advisor

​ 通过上面对AdvisorSupport源码的分析可以发现:虽然该类提供了addAdvisor、addAdvice方法,但其底层只有一个保存Advisor的属性List<Advisor> advisors. addAdvisor方法不用说肯定是直接将Advisor放到了advisors属性中,我们重点分析下addAdvice这个方法:

public void addAdvice(Advice advice) throws AopConfigException {
    int pos = this.advisors.size();
    addAdvice(pos, advice);
}

public void addAdvice(int pos, Advice advice) throws AopConfigException {
		Assert.notNull(advice, "Advice must not be null");
		if (advice instanceof IntroductionInfo) {//暂且不考虑IntroductionInfo情况,后面会另起篇章详解
			addAdvisor(pos, new DefaultIntroductionAdvisor(advice, (IntroductionInfo) advice));
		}  else if (advice instanceof DynamicIntroductionAdvice) {//暂且不考虑DynamicIntroductionAdvice情况,后面会另起篇章详解
			throw new AopConfigException("DynamicIntroductionAdvice may only be added as part of IntroductionAdvisor");
		}
		else {
			addAdvisor(pos, new DefaultPointcutAdvisor(advice));
		}
	}

如上图所示addAdvice方法底层最后都会调用到addAdvice(int pos, Advice advice)这个方法,可以将Advisor添加到指定的顺序。暂且只考虑这个方法中else分支中的情况,首先会将要添加的Advice包装为DefaultPointcutAdvisor ,然后在将包装好的Advisor添加到advisors属性中。

DefaultPointcutAdvisor这个构造器默认的切点为Pointcut.TRUE,即拦截所有的方法。

public DefaultPointcutAdvisor(Advice advice) {
	this(Pointcut.TRUE, advice);
}

综上所述,使用SpringAop时无论我们使用@Aspect注入了切面还是手动注入了AdviceAdvisor底层都会解析为Advisor进行处理。前面文章描述过Advisor的概念,一个Advisor包含一个切入点Pointcut和一个建议Advice。默认情况下AdvisedSupport会将自定义的Advice包装为DefaultPointcutAdvisor, 并且这个Advisor的切点为Pointcut.TRUE即对所有的类和方法都有效, 所以调用Advised#addAdvice()方法会将添加的Advice转为Advsior,并且该建议默认对所有类和方法都生效,相当于是一个全局的Advice.如果想针对某个类或方法做增强,那最好还是调用Advised#addAdvisor()方法添加我们自定义的Advisor,这样可以自己指定切入点。

维护方法与拦截器链的映射关系

上面分析AdvisedSupport源码时,有一个非常关键的方法getInterceptorsAndDynamicInterceptionAdvice,该方法会为代理方法生成拦截链和缓存该方法与拦截链的映射关系。

public class AdvisedSupport extends ProxyConfig implements Advised {

	AdvisorChainFactory advisorChainFactory = new DefaultAdvisorChainFactory();
	
	private transient Map<MethodCacheKey, List<Object>> methodCache;
	
	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;
	}
	
	.......
}
public interface AdvisorChainFactory {
	
	//为方法拦截链,拦截链由MethodInterceptor列表组成
	List<Object> getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, @Nullable Class<?> targetClass);
}

如上图所示可以看出该方法核心逻辑是通过AdvisorChainFactory为方法生成拦截链,顾名思义这个接口是生成拦截链(AdvisorChain), 默认使用的是DefaultAdvisorChainFactory实现。

DefaultAdvisorChainFactory
public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializable {

	@Override
	public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
			Advised config, Method method, @Nullable Class<?> targetClass) {
		
		//AdvisorAdapterRegistry用于保存AdvisorAdapter的注册中心,
		//其中AdvisorAdapter是用来将Advisor转为MethodInterceptor的
		AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
		
		//从AdvisedSupport中获取用户定义的所有Advisor
		Advisor[] advisors = config.getAdvisors();
		
		//定义一个集合用于保存AdvisorAdapter转换后生成的MethodInterceptor
		List<Object> interceptorList = new ArrayList<>(advisors.length);
		
		//从TargetSource中获取方法所在的类的类型
		Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
		
		//是否存在IntroductionAdvisor类型的Advisor
		//IntroductionAdvisor是AOP非常重要的Advisor类型,不常用但是有时很有用,后面单独起篇章剖析
		//此处先Mark一下
		Boolean hasIntroductions = null;

		for (Advisor advisor : advisors) {
			//处理PointcutAdvisor类型的Advisor,即带切入点的Advisor
			if (advisor instanceof PointcutAdvisor) {
				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()) {
							for (MethodInterceptor interceptor : interceptors) {
								interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
							}
						}
						else {
							interceptorList.addAll(Arrays.asList(interceptors));
						}
					}
				}
			}
			//用于处理IntroductionAdvisor类型的Advisor,此处先Mark一下
			//后面IntroductionAdvisor篇章再进行剖析
			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));
				}
			}
			//处理其他类型的,例如PrototypePlaceholderAdvisor或自定义的Advisor
			else {
				Interceptor[] interceptors = registry.getInterceptors(advisor);
				interceptorList.addAll(Arrays.asList(interceptors));
			}
		}

		return interceptorList;
	}

	
	//用于判断AdvisedSupport中的advisors是否有是IntroductionAdvisor类型的
	private static boolean hasMatchingIntroductions(Advisor[] advisors, Class<?> actualClass) {
		for (Advisor advisor : advisors) {
			if (advisor instanceof IntroductionAdvisor) {
				IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
				if (ia.getClassFilter().matches(actualClass)) {
					return true;
				}
			}
		}
		return false;
	}

}

​ 如上源码分析所示,getInterceptorsAndDynamicInterceptionAdvice方法核心功能是 : 首先通过GlobalAdvisorAdapterRegistry.getInstance()获取到AdvisorAdapterRegistry, 然后遍历所有的advisors,使用AdvisorAdapterRegistry将每个Advisor包装为 MethodInterceptor 添加到拦截链。到这边可以得出结果 : 拦截链底层是由 MethodInterceptor组成的。

​ 根据上面的分析可知,DefaultAdvisorChainFactory核心逻辑会委托给(将Advisor转为MethodInterceptorAdvisorAdapterRegistry ,下面我们就剖析下它。

AdvisorAdapterRegistry
//Advisor适配器注册中心接口
//这是一个SPI接口,任何Spring用户都不能实现
public interface AdvisorAdapterRegistry {

	//将Advice转为Avisor. 接口实现至少要实现这个方法
	Advisor wrap(Object advice) throws UnknownAdviceTypeException;

	//获取当前Advisor包含的MethodInterceptor
	//因为MethodInterceptor继承了Advice,所以这边也相当于获取Advisor中包含的Advice
	MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException;
	
	//注册AdvisorAdapter到AdvisorAdapterRegistry注册中心中
	void registerAdvisorAdapter(AdvisorAdapter adapter);
}

DefaultAdvisorChainFactory中是通过 GlobalAdvisorAdapterRegistry.getInstance()获取 AdvisorAdapterRegistry的。 如下所示可以看出GlobalAdvisorAdapterRegistry是一个典型的恶汉式单例模式, 用于获取DefaultAdvisorAdapterRegistry实现类,这也是SpringAop提供的唯一默认实现。

public final class GlobalAdvisorAdapterRegistry {

	private GlobalAdvisorAdapterRegistry() {}

	private static AdvisorAdapterRegistry instance = new DefaultAdvisorAdapterRegistry();

	public static AdvisorAdapterRegistry getInstance() {
		return instance;
	}

	static void reset() {
		instance = new DefaultAdvisorAdapterRegistry();
	}
}

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

	//根据Advice的具体类型将其包装为相应类型的Advisor
	@Override
	public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
		//如果本身为Advisor,则直接返回即可
		if (adviceObject instanceof Advisor) {
			return (Advisor) adviceObject;
		}
		
		if (!(adviceObject instanceof Advice)) {
			throw new UnknownAdviceTypeException(adviceObject);
		}
		
		Advice advice = (Advice) adviceObject;
		
		//MethodInterceptor类型的Advice将其包装为DefaultPointcutAdvisor
		if (advice instanceof MethodInterceptor) {
			return new DefaultPointcutAdvisor(advice);
		}
		
		//其他类型的Advice则需要检验adapters中的适配器是否支持处理当前类型的Advice
		//如果支持则包装为DefaultPointcutAdvisor
		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);
	}
}

如上图所示,DefaultAdvisorAdapterRegistry主要是借助 adapters属性中注册的适配器来完成wrap()、getInterceptors()实现的,逻辑比较简单。总的来说就是可以将Advice包装为Advisor,也可以返回Advisor包含的建议MethodInterceptor,这两个功能都会依赖adapters属性中保存的AdvisorAdapter来完成。下面我们就剖析下这个AdvisorAdapter是用来干嘛的。

AdvisorAdapter
public interface AdvisorAdapter {

	//判断SpringAop是否支持当前类型的Advice类型
	boolean supportsAdvice(Advice advice);

	//如果supportsAdvice方法支持当前Advisor中的Advice类型,则可以将Advisor包装为MethodInterceptor
	MethodInterceptor getInterceptor(Advisor advisor);
}

​ 如上图UML图所示,SpringAop默认提供了三个实现,有没有似曾相似的感觉呢? 前面文章说道SpringAop是基于AOP联盟中的标准接口来实现的,而AOP联盟中只提供了环绕通知建议(MethodInterceptor)。一般使用SpringAop时我们还经常用到@Before、@After、@AfterReturning、@AfterThrowing这些注解来定义前置通知、后置通知、返回值通知、异常通知,以上这些通知是SpringAop专门为AOP联盟Advice做的扩展建议。

​ 因为AOP联盟中只支持环绕通知,所以SpringAop针对这些扩展的通知会使用对应的AdvisorAdapter将其包装为MethodInterceptor . 这样这些扩展的通知就可以和环绕通知一样通过AOP联盟中的MethodInterceptor#invoke()通用方法运行。

​ 以前置通知的AdvisorAdapter实现MethodBeforeAdviceAdapter为例,getInterceptor方法会将前置通知包装为MethodBeforeAdviceInterceptor 。 它实际上就是 MethodInterceptor的是一个实现,只不过是在代理方法执行前做了增强而已,在方法执行之后什么都没做,本质上还是一个环绕通知。

//BeforeAdvice继承了Advice接口
public interface MethodBeforeAdvice extends BeforeAdvice {
	void before(Method method, Object[] args, @Nullable Object target) throws Throwable;
}

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

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();
	}
}
ProxyCreatorSupport
public class ProxyCreatorSupport extends AdvisedSupport {

	private AopProxyFactory aopProxyFactory;

	private final List<AdvisedSupportListener> listeners = new LinkedList<>();

	private boolean active = false;

	public ProxyCreatorSupport() {
		this.aopProxyFactory = new DefaultAopProxyFactory();
	}

	public ProxyCreatorSupport(AopProxyFactory aopProxyFactory) {
		Assert.notNull(aopProxyFactory, "AopProxyFactory must not be null");
		this.aopProxyFactory = aopProxyFactory;
	}

	public void setAopProxyFactory(AopProxyFactory aopProxyFactory) {
		Assert.notNull(aopProxyFactory, "AopProxyFactory must not be null");
		this.aopProxyFactory = aopProxyFactory;
	}

	public AopProxyFactory getAopProxyFactory() {
		return this.aopProxyFactory;
	}

	public void addListener(AdvisedSupportListener listener) {
		Assert.notNull(listener, "AdvisedSupportListener must not be null");
		this.listeners.add(listener);
	}

	public void removeListener(AdvisedSupportListener listener) {
		Assert.notNull(listener, "AdvisedSupportListener must not be null");
		this.listeners.remove(listener);
	}
	
	//生成代理对象
	protected final synchronized AopProxy createAopProxy() {
		if (!this.active) {
			activate();
		}
		return getAopProxyFactory().createAopProxy(this);
	}

	private void activate() {
		this.active = true;
		for (AdvisedSupportListener listener : this.listeners) {
			listener.activated(this);
		}
	}

	@Override
	protected void adviceChanged() {
		super.adviceChanged();
		synchronized (this) {
			if (this.active) {
				for (AdvisedSupportListener listener : this.listeners) {
					listener.adviceChanged(this);
				}
			}
		}
	}

	protected final synchronized boolean isActive() {
		return this.active;
	}

}

ProxyCreatorSupport整体比较简单,有两个点重点关注一下。第一个是createAopProxy()借助AopProxyFactory生成了SpringAop代理对象, 第二个是它还留了一个扩展点,当AdvisedSupport中的配置发生改变后会自动对List<AdvisedSupportListener> listeners中的监听器进行通知,这有时很有用。下面我们重点看下AopProxyFactory

AopProxyFactory
public interface AopProxyFactory {
	AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException;
}
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);
		}
	}
	
	//判断是否有指定代理的接口类型
	private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
		Class<?>[] ifcs = config.getProxiedInterfaces();
		return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
	}
}

SpringAop提供了一个默认实现 DefaultAopProxyFactory. 该工厂主要是通过AdvisedSupport中的代理相关配置决定使用JDK动态代理还是Cglib代理生成代理对象。判断条件如下:

  • 如果配置了optimizeproxyTargetClass属性为true,并且目标类是一个类而非接口则使用Cglib代理。如果目标类是一个接口,即使设置了这个两个属性为true也会使用JDK动态代理
  • 如果没有配置optimizeproxyTargetClass这两个属性(默认为false),并且有指定要代理的接口类型则会使用JDK代理。否则会根据目标对象是接口还是类决定使用Cglib代理还是JDK动态代理

这也解释了为什么在@EnableAspectJAutoProxy注解中配置proxyTargetClass=true就可以强制使用cglib代理,因为一般被代理的都是类。

AopProxy
public interface AopProxy {

	Object getProxy();

	Object getProxy(@Nullable ClassLoader classLoader);
}

如上所示AopProxy是对生成代理对象过程的抽象,这个是一个典型的策略模式。从UML图也可以看出SpringAop目前只提供了Cglib代理JDK动态代理的支持。至于CglibAopProxyJdkDynamicAopProxy具体生成代理对象的细节,此处先不表,后面文章将基于案例详细剖析。

总结

​ 本文简单剖析了下SpringAop底层原理过程中涉及到一些比较关键的接口和类。这些类组合到一起的核心功能就是 : 首先将用户定义的AdvisorAdvice底层都会转为Advisor并保存在AdvisedSupport中的advisors中。然后会按照advisors中顺序为每个需要代理的方法生成一条拦截链,底层生成这个链的过程就是将Advisor都转为 MethodInterceptor, 并连接起来组成链。最后返回代理对象,这样调用代理方法时,会对方法进行增强,所谓增强就是在各个拦截链中做了想做的事情(Advice).

​ 其实分析完这些关键的类,SpringAop的大致流程也就搞明白了。下篇文章将结合一个案例剖析下具体的代理过程细节。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值