Spring 之 @EnableAspectJAutoProxy 简单使用和源码分析

@EnableAspectJAutoProxy 的作用

此注解主要用来导入 Spring 切面功能类,借用 @Import 导入核心类,源码如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
// aop_step_1: 首先利用 @Import 注解导入了一个组件
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {

	boolean proxyTargetClass() default false;

	boolean exposeProxy() default false;
}

该注解包含两个属性:proxyTargetClass = true 表示通过 cglib 创建代理,反之 jdk 代理创建,但都是要根据类实际情况定(自己内部推测使用哪种代理方式)。exposeProxy = true 表示是否需要暴露代理对象,等于 true 表示把代理对象临时存放到 ThreadLocal 变量,在同一线程中不同地方就可从该变量中获取此代理对象。

然后再看 @Import 导入的类 AspectJAutoProxyRegistrar,源码如下:

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

	/**
	 * Register, escalate, and configure the AspectJ auto proxy creator based on the value
	 * of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
	 * {@code @Configuration} class.
	 */
	@Override
	public void registerBeanDefinitions(
			AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		/**
		 * aop_step_3: 往 Spring 容器中注册一个用于创建 AOP 代理类的 Class 定义
		 */
		AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);


		AnnotationAttributes enableAspectJAutoProxy =
				AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
		if (enableAspectJAutoProxy != null) {
			if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
				AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
			}
			if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
				AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
			}
		}
	}

}

直接进入 registerAspectJAnnotationAutoProxyCreatorIfNecessary() 方法的核心部分,如下:

	@Nullable
	public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
			BeanDefinitionRegistry registry, @Nullable Object source) {
		/** 通过注解 @EnableAspectJAutoProxy 导入类 AnnotationAwareAspectJAutoProxyCreator */
		// aop_step_4: 往 BeanDefinitionRegistry 容器中注册一个 AnnotationAwareAspectJAutoProxyCreator 类
		// AnnotationAwareAspectJAutoProxyCreator 该类是 BeanPostProcessor 和 SmartInstantiationAwareBeanPostProcessor 的子类
		// 可以查看 AnnotationAwareAspectJAutoProxyCreator 的继承图示
		return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
	}

从上述代码中可看出导入了一个 AnnotationAwareAspectJAutoProxyCreator 类,这个类就是 Spring AOP 切面的入口类。

AbstractAutoProxyCreator 抽象类

注意这个类又什么特点呢?看源码如下:

- BeanPostProcessor
	- AbstractAutoProxyCreator
		- AbstractAdvisorAutoProxyCreator
			- AspectJAwareAdvisorAutoProxyCreator
				- AnnotationAwareAspectJAutoProxyCreator

可以看出这个类是 Spring BeanPostProcessor 接口的应用。 BeanPostProcessor 接口设计非常灵活。这里主要关注 AbstractAutoProxyCreator#postProcessAfterInstantiation() 方法,因为主要逻辑在这个方法里面。AbstractAutoProxyCreator 这个抽象类把公共的核心逻辑写好,子类只需要重写其中的一些方法即可,这其实是模版设计模式的一种体现。

源码如下:

	@Override
	public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
		if (bean != null) {
			/** 获取缓存 key */
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			if (this.earlyProxyReferences.remove(cacheKey) != bean) {
				/** 找到合适的就会被代理 */
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}

上面这段逻辑就会创建代理对象。cacheKey 就是一个缓存 key,earlyProxyReferences 集合中装的是否已经被代理过,如果已经被代理过这里将不会重新创建代理。进入 wrapIfNecessary() 方法,核心源码如下:

	protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		 /**
		  * tc_tag-100: 去查找当前 bean 可以使用的增强器有哪些(@Before、@After...)
		  */
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);


		if (specificInterceptors != DO_NOT_PROXY) {
		 	/**
			 * 1.创建真正的代理对象,把所有 Advisor 的功能都封装到了代理类中,此时这个代理类功能强大的一批
			 * 2.把被代理对象封装到了 SingletonTargetSource 对象中
			 */
			Object proxy = createProxy(
					bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));

			return proxy;
		}

		return bean;
	}

上述一整段逻辑是先去判断这个类有哪些增强的 Advisor(比如你在代码中配置的 @Aspect 中 @Around、@Before 等修饰的方法 和 @Pointcut 条件组装成一个个 Advisor。或者是你自定义的 Advisor、或者 Advice 等等),如果找到有这些 Advisor 并且满足 @Pointcut 条件,就表示这个类是需要创建代理对象的,从而就会在这里创建出代理对象,Spring 单例缓冲池中存放的也是个代理对象,不是真正类实例。

现在先重点分析 getAdvicesAndAdvisorsForBean() 方法,看是如何找到这个类的代理增强的?

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

		List<Advisor> candidateAdvisors = findCandidateAdvisors();

		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);

		extendAdvisors(eligibleAdvisors);

		if (!eligibleAdvisors.isEmpty()) {
			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
		}
		return eligibleAdvisors;
	}

从上述源码就可以看出,findCandidateAdvisors() 方法就是去找到解析出所有的 Advisor,像 @Aspect 注解修饰的类里面的方法就被被解析成一个个的 Advisor。findAdvisorsThatCanApply() 方法就是判断这些看哪些 Advisor 适用于这个当前的 beanClass。

先进入 findCandidateAdvisors() 方法核心逻辑,源码如下:

	/**
	 * 重写父类的 findCandidateAdvisors() 方法
	 * @return
	 */
	@Override
	protected List<Advisor> findCandidateAdvisors() {
		/**
		 * 1.调用父类的方法去找出所有的 Advisor 类
		 * 2.正常情况,如果我们自己没有实现 Advisor 接口或者是没有导入其他切面(@Transactional等) 这里就是返回 null
		 * 3.比如事务切面自己实现了一个 Advisor 接口 ==> BeanFactoryTransactionAttributeSourceAdvisor 所以事物逻辑这里就能够解析到一个 Advisor
		 */
		List<Advisor> advisors = super.findCandidateAdvisors();

		/**
		 * 1.然后解析 Advisor 类(@Aspect 修饰的类) 相关的信息之后封装成一个 Advisor=Advice+Pointcut 通知
		 * 2.aspectJAdvisorsBuilder 变量在 initFactory() 就已经赋值好了,所以肯定不为 null
		 */

		if (this.aspectJAdvisorsBuilder != null) {
			advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
		}
		return advisors;
	}

看到 buildAspectJAdvisors() 方法核心逻辑,源码如下:

	public List<Advisor> buildAspectJAdvisors() {
	
		List<String> aspectNames = this.aspectBeanNames;

		if (aspectNames == null) {
			/** 做了 dcl 检查*/
			synchronized (this) {
				aspectNames = this.aspectBeanNames;
				if (aspectNames == null) {

					String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
							this.beanFactory, Object.class, true, false);

					/** 遍历从 IOC 容器中获取到的所有 bean 名称 */
					for (String beanName : beanNames) {
				
						/** 通过 beanName 去容器中获取到对应的 class 对象 */
						Class<?> beanType = this.beanFactory.getType(beanName, false);

						if (this.advisorFactory.isAspect(beanType)) {
							/** 如果找到了被注解 @Aspect 修饰的类则添加到 aspectNames 集合中 */
							aspectNames.add(beanName);
	
							List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);

							advisors.addAll(classAdvisors);
						}
					}

					this.aspectBeanNames = aspectNames;
					return advisors;
				}
			}
		}
	}
	@Override
	public boolean isAspect(Class<?> clazz) {
		return (hasAspectAnnotation(clazz) && !compiledByAjc(clazz));
	}

	private boolean hasAspectAnnotation(Class<?> clazz) {
		return (AnnotationUtils.findAnnotation(clazz, Aspect.class) != null);
	}

上面代码中通过 beanNamesForTypeIncludingAncestors() 方法把所有能扫描的类都加载出来,然后挨个判断类上是否有 @Aspect 注解修饰,这里为了方便就只配置了一个 @Aspect 修饰的类。如下所示:

@Aspect
@Configuration
public class JavAspect {

	@Pointcut("execution(* com.gwm.proxy..*.*(..))")
	public void pointcutGwm() {}

	@Before(value = "pointcutGwm()")
	public void beforeTest(JoinPoint joinPoint) {
		System.out.println("beforeTest log info ===================");
	}
}

判断如果有 @Aspect 修饰的类,那么就要开始对这个 JavAspect 类解析,因为 @Before 修饰的方法就是切面增强逻辑,必须要被解析出来才能够被 Spring 调用到。那么就需要进入 getAdvisors() 方法内部了,核心逻辑如下:

	@Override
	public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {

		for (Method method : getAdvisorMethods(aspectClass)) {

			Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
			if (advisor != null) {
				advisors.add(advisor);
			}
		}
		return advisors;
	}

从上面逻辑可以看出,会对 JavAspect 类的所有方法进行处理,具体怎么处理呢?肯定是将带有 @Before 等注解修饰的方法然后封装成一个个能够被 Spring 识别的对象。进入 getAdvisor() 方法内部,核心逻辑如下:

	@Override
	@Nullable
	public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
			int declarationOrderInAspect, String aspectName) {
		
		return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
				this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
	}

从上面代码中可以看出直接 new 了一个 InstantiationModelAwarePointcutAdvisorImpl 对象,继续进入内部逻辑,源码如下:

	public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
			Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
			MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {

		/**
		 * 第一个参数就是 Pointcut 赋值,此时赋值还是 pc1() 占位符表达式
		 */
		this.declaredPointcut = declaredPointcut;

		this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
		this.methodName = aspectJAdviceMethod.getName();
		this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
		this.aspectJAdviceMethod = aspectJAdviceMethod;
		this.aspectJAdvisorFactory = aspectJAdvisorFactory;
		this.aspectInstanceFactory = aspectInstanceFactory;
		this.declarationOrder = declarationOrder;
		this.aspectName = aspectName;

		if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
		}
		else {
			// A singleton aspect.
			this.pointcut = this.declaredPointcut;
			this.lazy = false;
			/**
			 * 开始去找到 @Before 对象的 Advice 接口---->AspectJMethodBeforeAdvice
			 */
			this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
		}
	}

继续进入 instantiateAdvice() 方法内部逻辑如下:

	private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
		Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
				this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
		return (advice != null ? advice : EMPTY_ADVICE);
	}

继续进入 getAdvice() 方法内部逻辑如下:


	@Override
	@Nullable
	public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
			MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {

		AbstractAspectJAdvice springAdvice;
		
		switch (aspectJAnnotation.getAnnotationType()) {
			/**
			 * 王者: Advice 的六中实现,其他类型都是不支持的
			 */
			case AtPointcut:
				if (logger.isDebugEnabled()) {
					logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
				}
				return null;
			case AtAround:
				springAdvice = new AspectJAroundAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
			case AtBefore:
				springAdvice = new AspectJMethodBeforeAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
			case AtAfter:
				springAdvice = new AspectJAfterAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
			case AtAfterReturning:
				springAdvice = new AspectJAfterReturningAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
				if (StringUtils.hasText(afterReturningAnnotation.returning())) {
					springAdvice.setReturningName(afterReturningAnnotation.returning());
				}
				break;
			case AtAfterThrowing:
				springAdvice = new AspectJAfterThrowingAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
				if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
					springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
				}
				break;
			default:
				throw new UnsupportedOperationException(
						"Unsupported advice type on method: " + candidateAdviceMethod);
		}
		return springAdvice;
	}

可以看到这段逻辑是将 JavaAspect 类中 @Before 注解修饰的方法逻辑封装到了 AspectJMethodBeforeAdvice 对象中,其他注解也是依照该注解进行封装。到时候在执行目标方法的时候,就可以通过 AspectJMethodBeforeAdvice 对象调用增强逻辑非常方便。

到了这一步 JavaAspect 类也已经解析完成,并且 @Before 修饰的方法也被封装到 Spring 中管理起来了!

至此 findCandidateAdvisors() 方法就算执行完成,就是将 Spring 中 @Aspect 修饰的类或者自定义的 Advisor 解析封装。然后下一步就是判断这些解析出来的 Advisor 能不能适用于当前类。如果适用那么就会生成代理对象。

进入 findAdvisorsThatCanApply() 方法核心逻辑如下:

	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;
			}
			// tc_tag-96: 开始 for 循环 candidateAdvisors 每个增强器,看是否能使用与这个 bean
			if (canApply(candidate, clazz, hasIntroductions)) {
				eligibleAdvisors.add(candidate);
			}
		}
		return eligibleAdvisors;
	}

继续进入 canApply() 方法核心逻辑,如下:

	public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {

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

从上面代码逻辑可以看出,先会判断这个类是否匹配 @Pointcut 条件(@Pointcut 中指定了哪些类或者方法才可以进行增强代理的),然后再判断方法是否匹配 @Pointcut 条件,如果两个都满足那么表示这个 Advisor 可以用于这个类或者这个类的方法增强。对于 @Pointcut 的匹配过程还是非常复杂的,这里就不过多赘述。如果是 @Transactional 这种还是非常简单,只需要找到方法上是否标注了这个注解就完事了,和 @Aspect 中的 @Pointcut 不是一个级别的匹配过程。

然后再回到最外面调用的地方,getAdvicesAndAdvisorsForBean() 方法就算完成解析了!源码如下:

	protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		 /**
		  * tc_tag-100: 去查找当前 bean 可以使用的增强器有哪些(@Before、@After...)
		  */
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);


		if (specificInterceptors != DO_NOT_PROXY) {
		 	/**
			 * 1.创建真正的代理对象,把所有 Advisor 的功能都封装到了代理类中,此时这个代理类功能强大的一批
			 * 2.把被代理对象封装到了 SingletonTargetSource 对象中
			 */
			Object proxy = createProxy(
					bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));

			return proxy;
		}

		return bean;
	}

然后根据 specificInterceptors 返回值来判断是否需要创建代理对象。如果有值返回,那肯定表示当前类肯定是被 @Aspect 类的 @Pointcut 条件扫描到了!所以需要增强,所以就需要创建代理对象。进入 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);
		}

		ProxyFactory proxyFactory = new ProxyFactory();
		/**
		 * 将 AnnotationAwareAspectJAutoProxyCreator 对象中的属性 Copy 到 ProxyFactory 代理工厂中
		 * 后面肯定都是拿到这个工厂进行操作
		 */
		proxyFactory.copyFrom(this);

		if (proxyFactory.isProxyTargetClass()) {
			// Explicit handling of JDK proxy targets (for introduction advice scenarios)
			if (Proxy.isProxyClass(beanClass)) {
				// Must allow for introductions; can't just set interfaces to the proxy's interfaces only.
				for (Class<?> ifc : beanClass.getInterfaces()) {
					proxyFactory.addInterface(ifc);
				}
			}
		}
		else {
			// No proxyTargetClass flag enforced, let's apply our default checks...
			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}
			else {
				evaluateProxyInterfaces(beanClass, proxyFactory);
			}
		}

		/** 在此去查找看是否有自定义实现的 Advisor,然后添加进来 */
		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);

		/** 把 advisors 赋值到 proxyFactory 中*/
		proxyFactory.addAdvisors(advisors);
		/** 把 targetSource 赋值到 proxyFactory 中*/
		proxyFactory.setTargetSource(targetSource);
		customizeProxyFactory(proxyFactory);
		/** 设置代理是否被冻结,在 JDK 代理中有用到*/
		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);
	}

从上述源码中可以看到,在这里会创建一个代理工厂 ProxyFactory,主要用来封装代理相关的成员。这其实也是 Spring 最喜欢干的事,动不动就将一大堆的东西用一个对象封装,也是为了传参方便,获取也比较容易。

同时也要注意下 proxyFactory.setTargetSource(targetSource); 中的 targetSource 类型是 SingletonTargetSource 单例类型的 targetSource。

然后进入 getProxy() 方法核心如下:

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

	@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.");
			}
			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
				return new JdkDynamicAopProxy(config);
			}
			return new ObjenesisCglibAopProxy(config);
		}
		else {
			return new JdkDynamicAopProxy(config);
		}
	}

进入 getProxy() 其中 JDK 动态代理创建源码如下:


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

其中 InvocationHandler 源码如下:

final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {

	@Override
	@Nullable
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Object oldProxy = null;
		boolean setProxyContext = false;

		/**
		 * 注意 AdvisedSupport advised 就是 ProxyFactory 对象
		 * 获取到 ProxyFactory 中的 targetSource 目标对象
		 */
		TargetSource targetSource = this.advised.targetSource;
		Object target = null;

		try {
			if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
				// The target does not implement the equals(Object) method itself.
				return equals(args[0]);
			}
			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);
			}
			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;
			/**
			 * 王者:tc_tag13: 在注解 @EnableAspectJAutoProxy(exposeProxy=true) 的设置,如果设置了 true 就会被存到 ThreadLocal 里面
			 * 可以让多线程共享(异步事务) 或者解决 this.update() 这种写法换成 AopContext.getCurrentProxy().update()
			 */
			if (this.advised.exposeProxy) {
				/**
				 * 王者: 是否有需要暴露这个代理对象,使用 ThreadLocal 让线程之间共享这个代理对象(异步事务)
				 */
				oldProxy = AopContext.setCurrentProxy(proxy);
				setProxyContext = true;
			}

			/**
			 * 获取到目标对象,真正被代理的实例 bean
			 */
			target = targetSource.getTarget();
			Class<?> targetClass = (target != null ? target.getClass() : null);

			/**
			 * tc_tag14: 其实这里就是去做 matches() 过程,看这个 method() 是否需要被增强(条件在 Pointcut 中存着)
			 * 然后如果需要,就会把适用于该方法的所有的 Advice或者 InterceptorAndDynamicMethodMatcher 对象,不一定都是 Advice 哦注意
			 * 增强逻辑拿出来之后,放到一个集合中,形成一个拦截器链
			 */
			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.
				/** 直接调用目标方法,不需要去调用 Advice 方法 */
				Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
				retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
			}
			else {

				/**
				 * tc_tag15: 开始方法调用,是一个拦截器进行调用 ReflectiveMethodInvocation.proceed()
				 * MethodInvocation 对象就是对 proxy, target, method, args, targetClass, chain 的一个封装
				 * 看构造方法就知道了
				 */
				MethodInvocation invocation =
						new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, 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);
			}
		}
	}
}

cglib 代理创建源码如下:

	@Override
	public Object getProxy(@Nullable ClassLoader classLoader) {

		try {
			// Configure CGLIB Enhancer...
			Enhancer enhancer = createEnhancer();
			if (classLoader != null) {
				enhancer.setClassLoader(classLoader);
				if (classLoader instanceof SmartClassLoader &&
						((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
					enhancer.setUseCache(false);
				}
			}
			enhancer.setSuperclass(proxySuperClass);
			enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
			enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
			enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));

			Callback[] callbacks = getCallbacks(rootClass);
			Class<?>[] types = new Class<?>[callbacks.length];
			for (int x = 0; x < types.length; x++) {
				types[x] = callbacks[x].getClass();
			}
			// fixedInterceptorMap only populated at this point, after getCallbacks call above
			enhancer.setCallbackFilter(new ProxyCallbackFilter(
					this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
			enhancer.setCallbackTypes(types);

			// Generate the proxy class and create a proxy instance.
			return createProxyClassAndInstance(enhancer, callbacks);
		}
		catch (CodeGenerationException | IllegalArgumentException ex) {
			throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
					": Common causes of this problem include using a final class or a non-visible class",
					ex);
		}
		catch (Throwable ex) {
			// TargetSource.getTarget() failed
			throw new AopConfigException("Unexpected AOP exception", ex);
		}
	}

其中 MethodInterceptor 源码如下:

	private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {

		private final AdvisedSupport advised;

		public DynamicAdvisedInterceptor(AdvisedSupport advised) {
			this.advised = advised;
		}

		@Override
		@Nullable
		public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
			Object oldProxy = null;
			boolean setProxyContext = false;
			Object target = null;
			TargetSource targetSource = this.advised.getTargetSource();
			try {
				if (this.advised.exposeProxy) {
					// 王者: 是否有需要暴露这个代理对象,使用 ThreadLocal 让线程之间共享这个代理对象(异步事务)
					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);
				List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
				Object retVal;
				// Check whether we only have one InvokerInterceptor: that is,
				// no real advice, but just reflective invocation of the target.
				if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
					// 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 = methodProxy.invoke(target, argsToUse);
				}
				else {
					// We need to create a method invocation...
					retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
				}
				retVal = processReturnType(proxy, target, method, retVal);
				return retVal;
			}
			finally {
				if (target != null && !targetSource.isStatic()) {
					targetSource.releaseTarget(target);
				}
				if (setProxyContext) {
					// Restore old proxy.
					AopContext.setCurrentProxy(oldProxy);
				}
			}
		}
	}

至此代理对象创建完成,接下来就是调用过程。这里以 JDK 代理方式演示调用过程。这里准备了一个简单的方法调用,代码如下:

@Component
public class Apple {

	public void add() {
		System.out.println("add......");
	}
}

因为 @Pointcut 会切到 Apple 类的 add() 方法,所以在调用 add() 方法时也触发调用 @Before 注解修饰的方法。因为 Apple 类实例此时是一个代理对象,所以调用 add() 方法时会触发 InvocationHandler 的调用,源码如下:

	@Override
	@Nullable
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Object oldProxy = null;
		boolean setProxyContext = false;

		/**
		 * 注意 AdvisedSupport advised 就是 ProxyFactory 对象
		 * 获取到 ProxyFactory 中的 targetSource 目标对象
		 */
		TargetSource targetSource = this.advised.targetSource;
		Object target = null;

		try {
			Object retVal;

			if (this.advised.exposeProxy) {
				oldProxy = AopContext.setCurrentProxy(proxy);
				setProxyContext = true;
			}

			target = targetSource.getTarget();
			Class<?> targetClass = (target != null ? target.getClass() : null);

			List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

			if (chain.isEmpty()) {
				Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
				retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
			}
			else {
				MethodInvocation invocation =
						new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
				retVal = invocation.proceed();
			}			
			return retVal;
		}
		finally {
			if (target != null && !targetSource.isStatic()) {
				// Must have come from TargetSource.
				targetSource.releaseTarget(target);
			}
			if (setProxyContext) {
				// Restore old proxy.
				AopContext.setCurrentProxy(oldProxy);
			}
		}
	}

getInterceptorsAndDynamicInterceptionAdvice() 方法会判断当前正在调用的方法是否需要被代理增强,如果需要那么就会执行 invocation.proceed() 方法,核心逻辑如下:

	@Override
	@Nullable
	public Object proceed() throws Throwable {
		// 使用索引递增的方式来递归调用,调到最后一个方法时将索引重置
		/** 判断是否使用了拦截器 */
		if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
			/** 调用目标方法,底层其实是通过使用反射调用的 method.invoke(object) */
			return invokeJoinpoint();
		}
		else {
			/**
			 * tc_tag: 判断拦截器是 Advice 类型就走开始这下面的逻辑
			 * 注意 this 是 MethodInvocation 对象哦 封装了很多东西
			 * - 代理类
			 * - 目标对象
			 * - 目标方法
			 * - 目标Class
			 * - 目标参数
			 * - 拦截器链条(集合中存放着)
			 * 将这么多参数包装成一个对象就是为了能够在方法之间传递比较方便,Spring 最喜欢干这个事情了
			 *
			 * 事物就是从这里开始调用的,假设 interceptorsAndDynamicMethodMatchers 就只配置了一个事物切面前提
			 * 由 TransactionInterceptor 器执行增强功能
			 *
			 */
			return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
		}
	}

这段逻辑有点类似递归链式调用,也不用纠结注意下就好!这里只需要看 @Before 注解调用,源码如下:

	@Override
	@Nullable
	public Object invoke(MethodInvocation mi) throws Throwable {
		/**
		 * 先调用 BeforeAdvice 的增强逻辑
		 */
		this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
		/**
		 * 然后由回去调用其他的拦截器链,注意这个对象是 MethodInvocation
		 * 所以又会调用回去 MethodInvocation 中的 proceed() 方法
		 */
		return mi.proceed();
	}

可以在这里看到,为什么 Apple 类的 add() 方法执行时会调用到 @Before 修饰的方法,就是这里 Spring 自己帮你调用的。其他注解(@Around 等)也是一个套路。

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

魔道不误砍柴功

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值