04.Spring Framework 源码解析之 AOP

1. 环境搭建

代码已经上传至 https://github.com/masteryourself/spring-framework,工程是 tutorial-spring-aop

2. 源码解析

详细的源码注释可参考 https://github.com/masteryourself/spring-framework

2.1 组件导入
2.1.1 流程分析

@EnableAspectJAutoProxy

@EnableAspectJAutoProxy 给容器中导入了 AspectJAutoProxyRegistrar 组件,这个组件会判断是否需要给项目中导入 AnnotationAwareAspectJAutoProxyCreator 组件(只要容器中没有叫 org.springframework.aop.config.internalAutoProxyCreator 的组件就会自动导入)

AnnotationAwareAspectJAutoProxyCreator

AnnotationAwareAspectJAutoProxyCreator 关系图如上,它实现了 SmartInstantiationAwareBeanPostProcessor 接口,所以我们重点可以关注 postProcessBeforeInstantiationpostProcessAfterInitialization 方法

2.2 创建代理
2.2.1 流程分析

Aop 流程图

2.2.2 核心代码剖析
1. org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#isInfrastructureClass
protected boolean isInfrastructureClass(Class<?> beanClass) {
	// 判断是否是【Advice】、【Pointcut】、【Advisor】、【AopInfrastructureBean】类型
	boolean retVal = Advice.class.isAssignableFrom(beanClass) ||
			Pointcut.class.isAssignableFrom(beanClass) ||
			Advisor.class.isAssignableFrom(beanClass) ||
			AopInfrastructureBean.class.isAssignableFrom(beanClass);
	if (retVal && logger.isTraceEnabled()) {
		logger.trace("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]");
	}
	return retVal;
}
2. org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator#shouldSkip
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
	// TODO: Consider optimization by caching the list of the aspect names
	// 获取候选的增强器,就是切面里的通知方法,包装成了【Advisor】类
	List<Advisor> candidateAdvisors = findCandidateAdvisors();
	for (Advisor advisor : candidateAdvisors) {
		// 判断是否是【AspectJPointcutAdvisor】增强器类型
		if (advisor instanceof AspectJPointcutAdvisor &&
				((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
			return true;
		}
	}
	// 调用父类的 shouldSkip() 方法,这里是返回 false
	return super.shouldSkip(beanClass, beanName);
}
3. org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary
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;
	}

	// Create proxy if we have advice.
	// 获取当前 bean 的所有增强器(通知方法)
	Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
	if (specificInterceptors != DO_NOT_PROXY) {
		this.advisedBeans.put(cacheKey, Boolean.TRUE);
		// 创建 bean 的代理对象
		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;
}
4. org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findEligibleAdvisors
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
	// 1. 找到候选的所有增强器
	List<Advisor> candidateAdvisors = findCandidateAdvisors();
	// 2. 找到能在当前 bean 适用的增强器
	List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
	extendAdvisors(eligibleAdvisors);
	// 3. 给增强器进行排序
	if (!eligibleAdvisors.isEmpty()) {
		eligibleAdvisors = sortAdvisors(eligibleAdvisors);
	}
	return eligibleAdvisors;
}
5. org.springframework.aop.framework.DefaultAopProxyFactory#createAopProxy
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.");
		}
		// 如果是接口或者是 Proxy 类型,使用 Jdk 动态代理
		if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
			return new JdkDynamicAopProxy(config);
		}
		// 否则是用 Cglib 动态代理
		return new ObjenesisCglibAopProxy(config);
	}
	else {
		return new JdkDynamicAopProxy(config);
	}
}
2.3 运行方法
2.3.1 流程分析

Aop 执行流程

2.3.2 核心代码剖析
1. org.springframework.aop.framework.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();
	// 获取 bean 的所有的增强器
	Advisor[] advisors = config.getAdvisors();
	// 初始化一个拦截器链
	List<Object> interceptorList = new ArrayList<>(advisors.length);
	Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
	Boolean hasIntroductions = null;
	// 遍历所有的增强器,将其转为 Interceptor
	for (Advisor advisor : advisors) {
		// 和切点有关的 Advisor
		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) {
					// 将 advisor 转换成 MethodInterceptor 拦截器
					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;
}
2. org.springframework.aop.framework.ReflectiveMethodInvocation#proceed
public Object proceed() throws Throwable {
	//	We start with an index of -1 and increment early.
	// currentInterceptorIndex 表示当前拦截器的索引,从 -1 开始
	// 如果没有拦截器执行执行目标方法,或者拦截器的索引和拦截器数组 -1 大小一样(指定到了最后一个拦截器)执行目标方法
	if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
	    // 执行目标方法
		return invokeJoinpoint();
	}
	// ++currentInterceptorIndex 会一直递增,每一个拦截器等待下一个拦截器执行完成返回以后再来执行,每次执行都会有不同的拦截器
	Object interceptorOrInterceptionAdvice =
			this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
	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.
			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);
	}
}
3. org.springframework.aop.interceptor.ExposeInvocationInterceptor#invoke
public Object invoke(MethodInvocation mi) throws Throwable {
	// invocation 是【ThreadLocal<MethodInvocation>】类型,它需要共享 MethodInvocation,第一次还没有放进去
	MethodInvocation oldInvocation = invocation.get();
	// 将 MethodInvocation 放到 ThreadLocal 中
	invocation.set(mi);
	try {
		// 执行 proceed 方法
		return mi.proceed();
	}
	finally {
		invocation.set(oldInvocation);
	}
}
4. org.springframework.aop.aspectj.AspectJAfterThrowingAdvice#invoke
public Object invoke(MethodInvocation mi) throws Throwable {
	try {
		// 如何方法正常返回,什么都不做
		return mi.proceed();
	}
	catch (Throwable ex) {
		// 如果抛出异常,执行异常通知
		if (shouldInvokeOnThrowing(ex)) {
			invokeAdviceMethod(getJoinPointMatch(), null, ex);
		}
		throw ex;
	}
}
5. org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor#invoke
public Object invoke(MethodInvocation mi) throws Throwable {
	// 先等方法调用完,获取结果
	Object retVal = mi.proceed();
	// 再调用返回通知
	this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
	return retVal;
}
6. org.springframework.aop.aspectj.AspectJAfterAdvice#invoke
public Object invoke(MethodInvocation mi) throws Throwable {
	try {
		// 先调用一个拦截器的 proceed() 方法
		return mi.proceed();
	}
	finally {
		// 无论如何都执行 后置通知
		invokeAdviceMethod(getJoinPointMatch(), null, null);
	}
}
7. org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor#invoke
public Object invoke(MethodInvocation mi) throws Throwable {
	// 先调用前置通知
	this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
	// 再调用拦截器链的 proceed() 方法
	return mi.proceed();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值