详谈Spring的AOP原理

文章目录

  • 一、AOP概述
    • 1、AOP是什么?
    • 2、什么场景下会使用到AOP?
    • 3、老弟工作中AOP的实现内容?
  • 二、AOP源码解析
    • 1、AOP的包及SPI解析类?
    • 2、AOP在Spring中的入口?
    • 3、DEBUG跟踪Spring AOP源码流程
    • 3.1 判断Bean的方法是否被增强
    • 3.2 创建Bean的代理对象
  • 三、总结

一、AOP概述

1、AOP是什么?

AOP是Spring中的一种动态技术,支持对类的方法的增强,在对象创建的过程中会判断该bean是否需要增强,该bean的class中是否有方法在切入点上,如果在切入点上会创建相应的切面,有切面的bean就会相应的去创建代理对象。
Spring生态技术中AOP的应用有很多,比如事务,通过增强方法拦截异常进行回滚等。

2、什么场景下会使用到AOP?

AOP是增强方法,在不修改源代码情况下,进行对方法功能等扩展,其场景有很多,比如,缓存,增强某个方法使得根据方法的参数进行缓存的维护,有缓存的走缓存返回无缓存的走原始方法内容获取。再比如,监控,监控某个方法的调用信息,成功或失败,将信息发送给统计端做实时QPS、tps、tp99等指标的统计,以及方法可用率的计算等。

3、老弟工作中AOP的实现内容?

老弟在平时的工作中AOP相关的内容使用的很有限,京东的基础设置比较全,如上述的监控,在监控组件的客户端都有提供相关的注解支持。
老弟就搞了一下缓存的注解增强的实现,截止目前,老弟开发了基于注解的缓存配置方案,该方案目前只适用于接口无参的方法,关于动态的key的注解配置目前还没想好怎么做。还有是基于注解实时设置Log4J2的自定义参数ID,简单来讲就是提取方法参数中的requestId,设置日志容器的参数,使得我们通过日志搜索引擎基于ID,快速搜索到单次请求的全链路的内容。

二、AOP源码解析

1、AOP的包及SPI解析类?

AOP的包是spring-aop,我们去IED项目下的External Libraries中找到 spring-aop 的jar,在META-INF目录中找到 spring.handlers 文件,文件中配置的是如下的内容。

http\://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler

故知,aop相关的自定义的内容是在AopNamespaceHandler中配置的,当然这是aop传统的自定义标签的解析的内容是在这里处理的(就不仔细过其中内容了,主要看注解的启动方式)。当下,aop开启的方式是基于注解,@EnableAspectJAutoProxy(proxyTargetClass = false,exposeProxy = true)
注解的内容:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {

	/**
	 * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
	 * to standard Java interface-based proxies. The default is {@code false}.
	 *
	 * true
	 * 1、目标对象实现了接口 - 使用CGLIB代理机制
	 * 2、目标对象没有实现接口(只有实现类) - 使用CGLIB代理机制
	 *
	 * false
	 * 1、目标对象实现了接口 - 使用JDK动态代理机制(代理所有实现了的接口)
	 * 2、目标对象没有接口(只有实现类) - 使用CGLIB代理机制
	 *
	 * 都是动态代理就是实现的方式不一样而已。
	 */
	boolean proxyTargetClass() default false;

	/**
	 * Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal}
	 * for retrieval via the {@link org.springframework.aop.framework.AopContext} class.
	 * Off by default, i.e. no guarantees that {@code AopContext} access will work.
	 * @since 4.3.1
	 */
	boolean exposeProxy() default false;

}

查看上述代码可知,EnableAspectJAutoProxy导入了@Import(AspectJAutoProxyRegistrar.class)类。

AspectJAutoProxyRegistrar类

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

	@Override
	public void registerBeanDefinitions(
			AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		/**
		 * AUTO_PROXY_CREATOR_BEAN_NAME 这个就是AOP入口类的 名称。
		 * 有时可能会有覆盖性操作,名称需要记住。
		 */
		/**
		 * 注册AOP入口类
		 */
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

		/**
		 * 与xml不同的是基于注解方式需要获取注解的属性配置,并设置进入beanDefinition中
		 *
		 * true
		 * 1、目标对象实现了接口 - 使用CGLIB代理机制
		 * 2、目标对象没有实现接口(只有实现类) - 使用CGLIB代理机制
		 *
		 * false
		 * 1、目标对象实现了接口 - 使用JDK动态代理机制(代理所有实现了的接口)
		 * 2、目标对象没有接口(只有实现类) - 使用CGLIB代理机制
		 */
		AnnotationAttributes enableAspectJAutoProxy =
				AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
		if (enableAspectJAutoProxy != null) {
			if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
				AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
			}
			if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
				AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
			}
		}
	}

}

上述注册类中实现了ImportBeanDefinitionRegistrar,在refresh中的invokeBeanFactoryPostProcessors(beanFactory);会执行到ConfigurationClassPostProcessor的内容,会具体执行:@import @importResource @Bean的逻辑,最终会执行到之前@Import中的AspectJAutoProxyRegistrar.class的registerBeanDefinitions这个方法。
该方法的内容:

  1. 注册AOP的入口类,AnnotationAwareAspectJAutoProxyCreator.class,这个类继承了AbstractAutoProxyCreator,而AbstractAutoProxyCreator这个类的顶层接口是BeanPostProcessor。所以在实例化的后置处理阶段会基于这个类判断对象是否有切面。
  2. 基于注解方式需要获取注解的属性配置,并设置进入beanDefinition中。
    proxyTargetClass为true,使用CGLIB代理机制。proxyTargetClass为false,目标对象实现了接口 - 使用JDK动态代理机制,目标对象没有接口(只有实现类) - 使用CGLIB代理机制。

2、AOP在Spring中的入口?

在DI依赖注入后,需要进行bean实例化的后置处理,有一些初始化方法,在最后还会进行AOP的判断。
AbstractAutowireCapableBeanFactory -> initializeBean

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
// ... ... 省略Aware接口调用,@postConstruct,initializeBean接口调用,init-method方法调用省略
        /**
		 *  Aop入口,有切面的实例才会被代理。
		 */
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}
		return wrappedBean;
	}

AbstractAutowireCapableBeanFactory -> applyBeanPostProcessorsAfterInitialization

	public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
			throws BeansException {
		/**
		 * AOP的入口是一个BeanPostProcessor的应用,是抽象类AbstractAutoProxyCreator
		 *
		 * 抽象类AbstractAutoProxyCreator的子类是何时注入进来的?
		 *	解析自定义xml 或 注解扫描过程中某个Bean的信息有 @EnableAspectJAutoProxy
		 * Spring保存的是代理对象还是被代理对象?
		 *	被代理的对象
		 */
		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
			Object current = processor.postProcessAfterInitialization(result, beanName);
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
	}

关键判断Bean是否有切面是否创建代理对象的方法。
AbstractAutoProxyCreator -> postProcessAfterInitialization

	@Override
	public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
		if (bean != null) {
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			if (!this.earlyProxyReferences.contains(cacheKey)) {
				/**
				 * 关键方法 主要是看bean是否有切面。有切面就给这个bean创建代理对象
				 */
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}

3、DEBUG跟踪Spring AOP源码流程

AbstractAutoProxyCreator -> wrapIfNecessary

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

		/**
		 * 如果当前bean需要被代理就会返回一个不为空的切面数组( Object[])。
		 * 主要是找bean相关的advisor切面数组。
		 * 重要程度:* * * * *
		 */
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		/**
		 * 如果有切面则生成该Bean的代理
		 */
		if (specificInterceptors != DO_NOT_PROXY) {
			this.advisedBeans.put(cacheKey, Boolean.TRUE);
			/**
			 * 把被代理对象bean实例封装到SingletonTargetSource对象中
			 * TargetSource 这种接口的实现类 封装的是被代理的对象
			 * 创建代理对象
			 */
			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;
	}

上述方法主要内容是,先调用getAdvicesAndAdvisorsForBean判断当前bean是否有切面数组,如果有切面数组则需要进行代理。代理调用的方法式createProxy方法,会根据不同的情况使用不同的动态代理技术。

3.1 判断Bean的方法是否被增强

AbstractAdvisorAutoProxyCreator -> getAdvicesAndAdvisorsForBean

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

		/**
		 * 找到合格的切面,重点看
		 * 搜集@Aspectj的所有类
		 */
		List advisors = findEligibleAdvisors(beanClass, beanName);
		if (advisors.isEmpty()) {
			return DO_NOT_PROXY;
		}
		return advisors.toArray();
	}

继续调用findEligibleAdvisors方法寻找切面。
AbstractAdvisorAutoProxyCreator -> findEligibleAdvisors

	protected List findEligibleAdvisors(Class beanClass, String beanName) {
		// 找到候选的切面过程,其实就是找有@Aspectj注解的过程,把工程中所有有注解的类封装到Advisor返回。
		// 为什么是候选?需要代理的类是beanClass,findCandidateAdvisors是找到所有的切面。
		// 重点
		List candidateAdvisors = findCandidateAdvisors();

		// 判断后选切面是否作用在当前beanClass上面,就是一个匹配的过程,过滤掉不需要拦截beanClass类的切面。
		// 简单理解就是判断这个类是否在那个pointcut表达式里面
		List eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
		extendAdvisors(eligibleAdvisors);
		if (!eligibleAdvisors.isEmpty()) {
			// 对有@Order @Priority进行排序
			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
		}
		// 类在表达式里面就说明这个类绝对会生成代理
		return eligibleAdvisors;
	}

上述方法重点是调用 findCandidateAdvisors 方法获取工程中所有有@Aspectj注解的类封装到Advisor中返回,Advisor代指切面。

AnnotationAwareAspectJAutoProxyCreator -> findCandidateAdvisors

	@Override
	protected List findCandidateAdvisors() {
		// Add all the Spring advisors found according to superclass rules.
		List advisors = super.findCandidateAdvisors();
		// Build Advisors for all AspectJ aspects in the bean factory.
		/**
		 * 创建候选的切面 buildAspectJAdvisors
		 */
		if (this.aspectJAdvisorsBuilder != null) {
			advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
		}
		return advisors;
	}

主要看创建候选切面的内容,this.aspectJAdvisorsBuilder.buildAspectJAdvisors 方法的调用。

BeanFactoryAspectJAdvisorsBuilder -> buildAspectJAdvisors

	public List buildAspectJAdvisors() {
		// ... ...
					/**
					 * 拿到beanFactory中所有beanDefinition的名称
					 */
					String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
							this.beanFactory, Object.class, true, false);
					for (String beanName : beanNames) {
						// ... ...

						// 判断类上是否有@Aspectj注解
						if (this.advisorFactory.isAspect(beanType)) {
							aspectNames.add(beanName);
							AspectMetadata amd = new AspectMetadata(beanType, beanName);
							if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {

								// 创建获取有@Aspectj注解类的工厂实例,负责获取所有@Aspectj注解类的实例
								MetadataAwareAspectInstanceFactory factory =
										new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
								/**
								 * 创建切面advisor实例
								 */
			List classAdvisors = this.advisorFactory.getAdvisors(factory);
								if (this.beanFactory.isSingleton(beanName)) {
									this.advisorsCache.put(beanName, classAdvisors);
								}
								else {
							this.aspectFactoryCache.put(beanName, factory);
								}
							advisors.addAll(classAdvisors);
							}
							// ... ...
						}
					}
					this.aspectBeanNames = aspectNames;
					return advisors;
				}
			}
		}
// ... ...
		return advisors;
	}

上述方法主要内容是遍历 BeanDefinition,判断类上是否有@AspectJ注解,建获取有@Aspectj注解类的工厂实例,负责获取所有@Aspectj注解类的实例。
调用 getAdvisors 方法,创建切面信息。

ReflectiveAspectJAdvisorFactory -> getAdvisors 创建切面数组

	public List getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
		// 从工厂中获取有@Aspectj注解的class
		Class aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
		// 从工厂中获取有@Aspectj注解的类的名称
		String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
		validate(aspectClass);

		// 创建工厂的装饰类,获取实例只会获取一次
		// We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
		// so that it will only instantiate once.
		MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
				new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

		/**
		 * 循环没有@PointCut注解的方法,pointCut是一个切点并非是一个增强方法。
		 *
		 * @PointCut 里面只有一个表达式,并非是增强的内容
		 */
		List advisors = new ArrayList<>();
		for (Method method : getAdvisorMethods(aspectClass)) {
			/**
			 * 这里比较重要,创建advisor。
			 */
			Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
			if (advisor != null) {
				advisors.add(advisor);
			}
		}

		// ... ... 

		// 判断属性上是否有引介注解
		// Find introduction fields.
		for (Field field : aspectClass.getDeclaredFields()) {

			// 判断属性上是否有DeclareParennts注解,如果有返回切面
			Advisor advisor = getDeclareParentsAdvisor(field);
			if (advisor != null) {
				advisors.add(advisor);
			}
		}

		return advisors;
	}

该方法首先是从工厂中获取有@AspectJ注解的Class,获取有@Aspectj注解的类的名称,循环没有@PointCut注解的方法(实际功能方法并非是切入点),调用getAdvisor方法创建切面。不断的加入到advisors这个列表中。

ReflectiveAspectJAdvisorFactory -> getAdvisor 创建切面

	public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
			int declarationOrderInAspect, String aspectName) {

		validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());

		// 获取pointCut对象,主要是从注解中提取表达式
		AspectJExpressionPointcut expressionPointcut = getPointcut(
				candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
		if (expressionPointcut == null) {
			return null;
		}

		// 创建Advisor切面类,这才是真正的切面类,一个切面类中肯定要有 pointCut 和 advice
		// 这里pointCut是expressionPointcut,advice增强方法是candidateAdviceMethod
		return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
				this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
	}

上述getAdvisor中,获取pointCut对象,主要是从注解中提取表达式。 创建Advisor切面类,这才是真正的切面类,一个切面类中肯定要有 pointCut 和 advice,这里pointCut是expressionPointcut,advice增强方法是candidateAdviceMethod。其实最终创建出来的数组就是增强方法的数组 Interceptors,就是下述方法 getAdvice 创建的东西。

Advice 增强内容的创建

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

		// 获取有@Aspectj注解的类
		Class candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
		validate(candidateAspectClass);

		// 找到candidateAdviceMethod方法上面的注解,并且包装成AspectJAnnotation对象,这个对象中就有注解类型
		AspectJAnnotation aspectJAnnotation =
				AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
		if (aspectJAnnotation == null) {
			return null;
		}
        // ... ...
		AbstractAspectJAdvice springAdvice;

		// advice创建,增强创建
		// 根据不同的注解类型来创建不同的advice
		// 代理类调用方法时所有的advice对象会包装成MethodInterceptor对象。前置增强和拿到返回值后置通知没实现MethodInterceptor接口
		switch (aspectJAnnotation.getAnnotationType()) {
			case AtPointcut:
				if (logger.isDebugEnabled()) {
					logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
				}
				return null;
			case AtAround:
				// 实现了MethodInterceptor接口
				springAdvice = new AspectJAroundAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
			case AtBefore:
				// 实现了MethodBeforeAdvice接口
				springAdvice = new AspectJMethodBeforeAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
			case AtAfter:
				// 实现了MethodInterceptor接口
				springAdvice = new AspectJAfterAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
			case AtAfterReturning:
				// 实现了AfterReturningAdvice接口,没有实现MethodInterceptor接口
				springAdvice = new AspectJAfterReturningAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
				if (StringUtils.hasText(afterReturningAnnotation.returning())) {
					springAdvice.setReturningName(afterReturningAnnotation.returning());
				}
				break;
			case AtAfterThrowing:
				// 实现了MethodInterceptor接口
				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;
	}

基于切入点和advie创建实际的advice,获取有@Aspectj注解的类,找到candidateAdviceMethod方法上面的注解,并且包装成AspectJAnnotation对象,这个对象中就有注解类型,根据不同的注解类型来创建不同的advice。 代理类调用方法时所有的advice对象会包装成MethodInterceptor对象。前置增强和拿到返回值后置通知没实现MethodInterceptor接口

3.2 创建Bean的代理对象

AbstractAutoProxyCreator -> createProxy

	protected Object createProxy(Class beanClass, @Nullable String beanName,
			@Nullable Object[] specificInterceptors, TargetSource targetSource) {

		// ......

		// 创建代理工厂
		ProxyFactory proxyFactory = new ProxyFactory();
		proxyFactory.copyFrom(this);

		// ......

		// 把advice类型的增强 包装成advisor切面。
		// 本身已经是advisor,为什么还要包装一下advisor
		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		proxyFactory.addAdvisors(advisors);
		proxyFactory.setTargetSource(targetSource);
		customizeProxyFactory(proxyFactory);

		// 用来控制代理工程被配置后是否还允许修改代理的配置,默认为false
		proxyFactory.setFrozen(this.freezeProxy);
		if (advisorsPreFiltered()) {
			proxyFactory.setPreFiltered(true);
		}

		// 获取代理的实例
		return proxyFactory.getProxy(getProxyClassLoader());
	}

这里会把传进来的specificInterceptors,调用 buildAdvisors 方法统一整理,对自定义的advice要进行包装,把advice包装成advisor对象,切面对象。

getProxy方法首先要判断使用哪种动态代理的技术.
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.");
			}
			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
				return new JdkDynamicAopProxy(config);
			}
			return new ObjenesisCglibAopProxy(config);
		}
		else {
			return new JdkDynamicAopProxy(config);
		}
	}

JDK Proxy
JdkDynamicAopProxy -> getProxy

	public Object getProxy(@Nullable ClassLoader classLoader) {
		if (logger.isTraceEnabled()) {
			logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
		}
		/**
		 * jdk的动态代理
		 */
		Class[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
		findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
		// 拿到接口 proxiedInterfaces,h:this是InvocationHandler接口的实现类的实例
		// 当前的类JdkDynamicAopProxy实现了InvocationHandler,当前类有invoke方法
		return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
	}

JdkDynamicAopProxy实现了InvocationHandler接口,同样他就有invoke方法。

	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		/**
		 * invoke方法
		 */
		MethodInvocation invocation;
		Object oldProxy = null;
		boolean setProxyContext = false;

		// 从代理工厂拿到TargetSource对象,该对象包装了被代理实例bean
		TargetSource targetSource = this.advised.targetSource;
		Object target = null;

		try {
			// 被代理对象的equals方法和hashcode方法是不能被代理的,不会走切面
			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);
			}
			// ... ... 
			Object retVal;
			// exposeProxy 属性 是否暴露代理对象
			if (this.advised.exposeProxy) {
				// Make invocation available if necessary.
				// 代理对象,会放入threadLocal ,
				oldProxy = AopContext.setCurrentProxy(proxy);
				setProxyContext = true;
			}
			// target 就是一个被代理的实例
			target = targetSource.getTarget();
			Class targetClass = (target != null ? target.getClass() : null);

			// 从代理工厂中拿过滤器链条 Object是一个MethodInterceptor类型的对象,其实就是一个advice对象
			List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

			// chain 如果为空是当前方法没有增强,直接反射调用,但是还是走代理。
			if (chain.isEmpty()) {
				Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
				retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
			}
			else {
				// 不为空执行这个增强的链条调用  chain 就是执行链
				invocation = new ReflectiveMethodInvocation(
						proxy, target, method, args, targetClass, chain
				);
				// Proceed to the joinpoint through the interceptor chain.
				retVal = invocation.proceed();
			}

			// ... ... 
	}

 
  

关键的点就是:

  1. 被代理对象的equals方法和hashcode方法是不能被代理的,不会走切面
  2. 如果调用链为空是当前方法没有增强,直接反射调用,但是还是走代理。
  3. 调用链不为空,就会按增强列表顺序进行链式调用。

三、总结

AOP的内容就是增强我们的方法,在增强方法的设计上是采用动态代理的模式进行动态调用的。JDK 动态代理的链式调用,可以理解为我把这个bean的增强的方法串在一起,前置增强,环绕增强,后置增强等链式调用。

你可能感兴趣的:(Spring)