SpringAop 源码解析

 (一) - Aspect 切面方法的查找匹配过程

一、SpringAop Aspect 切面方法的查找匹配过程

SpringAop 是在项目中经常需要使用的框架,可以用来实现无侵入的逻辑增强。在使用 Aop 时,只需定义一个 Aspect 类,并加上相应的注解,Spring 内部已经帮我们封装好了代理过程,我们只需将精力放在对应的通知方法中即可。

比如有下面 bean 类:

@Component
public class TestAop {

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

然后再定义一个 Aspect 类:

@Aspect
@Component
@EnableAspectJAutoProxy(exposeProxy = true)
public class GlobAop {
    /**
     * 定义切入点
     */
    @Pointcut("execution(public * com.demo.test.*.*(..)))")
    public void BrokerAspect(){
    }


    @Before("BrokerAspect()")
    public void doBeforeGame(JoinPoint jp){
        String name = jp.getSignature().getName();
        System.out.println(name+"方法开始执行!");
    }

    @After("BrokerAspect()")
    public void doAfterGame(JoinPoint jp){
        String name = jp.getSignature().getName();
        System.out.println(name+"方法执行结束!");
    }


    @AfterReturning(value = "BrokerAspect()",returning = "result")
    public void doAfterReturningGame(JoinPoint jp, Object result){
        String name = jp.getSignature().getName();
        System.out.println(name+"方法返回 = " + result);

    }

    @AfterThrowing(value = "BrokerAspect()",throwing = "e")
    public void doAfterThrowingGame(JoinPoint jp, Exception e){
        String name = jp.getSignature().getName();
        System.out.println(name+"方法异常通知:"+e.toString());
    }

    @Around("BrokerAspect()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        return pjp.proceed();
    }
}

使用时也只关心需要的 bean:

public class App {

    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext("com.demo.test");
        TestAop testAop = context.getBean("testAop", TestAop.class);
        testAop.test();
    }

}

在这里插入图片描述

从这个案例中可以看出 SpringAop 使用起来完全无侵入,只需定好 Aspect 类和对应的切面方法即可生效,下面一起从源码的角度分析下Aspect 切面方法的查找和匹配过程。

在源码分析的过程涉及到 Spring bean 加载的过程 和 BeanPostProcessor 扩展接口,两个知识点,不了解的可以参考下面两篇博客:

Spring 源码解析 - Bean创建过程 以及 解决循环依赖

Spring 源码解析 - BeanPostProcessor 扩展接口

二、@EnableAspectJAutoProxy 做了什么

在使用 Aop 前,需要使用 @EnableAspectJAutoProxy 注解开启 Aop 的支持,这里从该注解着手开始分析,先看下该注解:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
// 开启 Aspectj自动代理
// 在springboot中,默认是会配置这个注解,并且默认用的是 cglib的代理,与之相对的是,spring默认用的是 jdk接口代理
@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}.
	 */
	//是否使用CGLIB代理和@AspectJ自动代理支持,该属性为true时,代表需要支持
	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;

}

该注解使用 @Import 引入了 AspectJAutoProxyRegistrar 类,这个类其实是个动态代理的 bean生成处理器,看到该类下:

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

		// 这个方法在工厂中,注册了一个 AspectJ注解的自动代理生成器
		AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

		AnnotationAttributes enableAspectJAutoProxy =
				AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
		// 这里类似于工厂后置方法,根据注解,修改bean定义
		if (enableAspectJAutoProxy != null) {
			if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
				AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
			}
			if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
				AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
			}
		}
	}

}

由于该类实现了 ImportBeanDefinitionRegistrar 接口,因此 Spring 启动时会触发 registerBeanDefinitions 方法,在该方法中会触发了 AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary 方法,其实是在注册动态代理的 bean生成处理器,进到该方法下:

在这里插入图片描述

这里实际触发的 registerOrEscalateApcAsRequired 方法,并传入了 AnnotationAwareAspectJAutoProxyCreator.class,这个就是动态代理的 bean生成处理器,看到该方法下注册的过程:

private static BeanDefinition registerOrEscalateApcAsRequired(
		Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
	//断言判断注册容器是否为空
	Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
	
	//如果AUTO_PROXY_CREATOR_BEAN_NAME已经注册过了
	if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
		//取出已经注册过的AUTO_PROXY_CREATOR_BEAN_NAME
		BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
		//判断是不是同一个Class对象
		if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
			//如果不是同一个对象,那就需要根据优先级来判断到底需要使用哪一个了
			//获取当前AOP自动代理创建器的优先级
			int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
			//获取指定的AOP自动代理创建器的优先级
			int requiredPriority = findPriorityForClass(cls);
			//进行优先级比较
			if (currentPriority < requiredPriority) {
				//如果指定的大于现在的,apcDefinition改变AOP自动代理创建器的class类型
				//相当于进行升级动作
				//由此可见,此时AOP自动代理创建器还没有实例出来,
				//这里只是将Aop自动代理创建其的BeanDefinition的className进行修改
				apcDefinition.setBeanClassName(cls.getName());
			}
		}
		//如果是同一个Class对象,证明是同一个处理器
		//返回,不需要进行注册
		return null;
	}

	//如果还没进行注册
	//使用Class去创建RootBeanDefinition,这里仅仅只是注入Class
	//从上面代码中可以看到,是可以进行更改的
	RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
	//封装一些信息
	beanDefinition.setSource(source);
	beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
	beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
	//注册进容器中,并且以AUTO_PROXY_CREATOR_BEAN_NAME为key
	registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
	return beanDefinition;
}

就是通过 BeanDefinitionRegistry 向 Spring IOC 容器中注入了 AnnotationAwareAspectJAutoProxyCreator 类。

三、AnnotationAwareAspectJAutoProxyCreator 做了什么

上一步已经得出 @EnableAspectJAutoProxy,就是向 Spring IOC 中注入了 AnnotationAwareAspectJAutoProxyCreator 类,这里看下 AnnotationAwareAspectJAutoProxyCreator 的继承关系:

在这里插入图片描述

从继承树中可以看出 AnnotationAwareAspectJAutoProxyCreator 通过 BeanPostProcessor 获取 bean 初始化前后通知能力,从 SmartInstantiationAwareBeanPostProcessor 获得循环依赖时早期实例曝光能力,通过 ProxyProcessorSupport 获得代理能力。

这里关注下 BeanPostProcessor 扩展接口,在 BeanPostProcessor 中有 postProcessBeforeInitialization 和 postProcessAfterInitialization 两个重要的前后通知方法,而这两个方法和 Spring bean 初始化过程紧密相关,方法如下:

public interface BeanPostProcessor {
	/**
	 *  实例化及依赖注入完成后、bean 初始化方法触发之前执行
	 */
	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

	/**
	 *  bean 初始化方法触发后执行
	 */
	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

}

如果还不了解 BeanPostProcessor 这里也简单提一下, BeanPostProcessor 的前后两个通知方法在 Spring 实例化过程中 AbstractAutowireCapableBeanFactory 类 initializeBean 方法中会被触发,如果通知方法返回的 bean 不为空就替换掉原先的 bean ,因此 BeanPostProcessor 有控制 bean 生成实例的能力,这也是为什么主要对他分析:

在这里插入图片描述

由于 AnnotationAwareAspectJAutoProxyCreator 类及其父类并没有对 postProcessBeforeInitialization 方法进行重写,而 postProcessAfterInitialization 方法在父类 AbstractAutoProxyCreator 类下有重写,因此这里可以猜测在postProcessAfterInitialization 方法中生成了代理对象,可以 debug 下AbstractAutowireCapableBeanFactory 类的 initializeBean 方法验证一下:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

从 debug 的过程可以看出在 postProcessAfterInitialization 方法确实创建了一个代理对象,并且最后使用的也是代理对象,下面就主要分析下 AbstractAutoProxyCreator 类下的 postProcessAfterInitialization 方法。

进入到 AbstractAutoProxyCreator 类的 postProcessAfterInitialization 方法中:

public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
	//某个bean 已经实例化后
	if (bean != null) {
		//获取缓存的键名,这里的形式是beanClassName_beanName
		Object cacheKey = getCacheKey(bean.getClass(), beanName);
		//判断是否已经提前曝光代理过
		if (this.earlyProxyReferences.remove(cacheKey) != bean) {
			//如果没被代理过,执行wrapIfNecessart
			return wrapIfNecessary(bean, beanName, cacheKey);
		}
	}
	//如果bean为Null,直接返回,如果不为null,但已经被曝光出来,直接返回bean
	//解决了循环依赖的问题
	return bean;
}

这里判断了 earlyProxyReferences 是否有缓存过该 bean ,这样做的目的是在循环依赖的情况下是否已经提前曝光代理对象了,看过Spring 源码的应该知道,三级缓存中存储的是一个 ObjectFactory,通过 getObject 获取早期实例,在Spring 放入三级缓存时,实际getObject 方法会触发 AbstractAutowireCapableBeanFactory 类的 getEarlyBeanReference 方法,逻辑如下:

在这里插入图片描述

这里会使用 SmartInstantiationAwareBeanPostProcessor 类型的通知器的 getEarlyBeanReference 方法获取一个早期实例,而AnnotationAwareAspectJAutoProxyCreator 也实现了 SmartInstantiationAwareBeanPostProcessor 因此会调用 getEarlyBeanReference 方法尝试获取一个早期对象,逻辑如下:

public Object getEarlyBeanReference(Object bean, String beanName) {
	Object cacheKey = getCacheKey(bean.getClass(), beanName);
	this.earlyProxyReferences.put(cacheKey, bean);
	return wrapIfNecessary(bean, beanName, cacheKey);
}

这里先对 earlyProxyReferences 容器中加入了缓存,然后调用 wrapIfNecessary 方法生成代理对象,同样在上面的 postProcessAfterInitialization 方法中,如果 earlyProxyReferences 中不存在或者存在的和当前不是一个实例也会执行 wrapIfNecessary 方法获取代理对象。

下面就来分析 wrapIfNecessary 方法,进到该方法下:

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
	//判断是不是已经增强过,根据 targetSourcedBeans 容器里面已经包含了这个 beanName
	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)) {
		//在 advusedBeans 容器增加标识,后面再出现直接中断
		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}

	// Create proxy if we have advice.
	// 根据beanName拿到需要增强的方法
	Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
	//是否存在增强方法
	if (specificInterceptors != DO_NOT_PROXY) {
		//如果存在增强方法,写入标识,代表正在需要进行增强
		this.advisedBeans.put(cacheKey, Boolean.TRUE);
		//创建代理
		Object proxy = createProxy(
				bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
		//保存代理的Class类型
		this.proxyTypes.put(cacheKey, proxy.getClass());
		//返回代理实例
		return proxy;
	}
	//如果不存在增强方法,则不需要进行代理
	//写入标识,后面再出现直接中断
	this.advisedBeans.put(cacheKey, Boolean.FALSE);
	// 返回当前实例
	return bean;
}

这里主要通过 getAdvicesAndAdvisorsForBean 方法,根据 beanName 获取到所有匹配的增强方法,也就是Aspect 中的切面方法,本篇文章重点分析的逻辑就在这里。

getAdvicesAndAdvisorsForBean 方法是个抽象方法,具体实现在 AbstractAdvisorAutoProxyCreator 类下,看该方法下:

protected Object[] getAdvicesAndAdvisorsForBean(
		Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
	//获取增强方法
	List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
	//判断是否为空
	if (advisors.isEmpty()) {
		//如果为空,返回一个空数组
		return DO_NOT_PROXY;
	}
	//如果不为空,转化为数组然后返回
	return advisors.toArray();
}

这里又调用 findEligibleAdvisors 方法获取当前 bean 匹配的增强方法,如果是空的话,则返回一个固定的空数组,在 wrapIfNecessary 方法中如果是这个固定的空数组,则标记直接返回,后续该类也直接返回不做处理。

下面进到 findEligibleAdvisors 方法中:

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
	//获取所有的增强方法
	List<Advisor> candidateAdvisors = findCandidateAdvisors();
	//从所有的增强方法中匹配适合该 bean 的增强方法
	List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
	//对匹配后的增强方法进行扩展
	extendAdvisors(eligibleAdvisors);
	//判断是否为空
	if (!eligibleAdvisors.isEmpty()) {
		//如果不为空,进行排序
		eligibleAdvisors = sortAdvisors(eligibleAdvisors);
	}
	//返回处理后的增强方法
	return eligibleAdvisors;
}

这里使用 findAdvisorsThatCanApply 查找全部的增强方法,使用findAdvisorsThatCanApply 匹配出适合当前类的增强方法,这两个方法也是本篇的核心,下面挨个来分析下。

三、查找 Aspect 切面方法

findCandidateAdvisors 方法主要看 AnnotationAwareAspectJAutoProxyCreator 类下的重载:

protected List<Advisor> findCandidateAdvisors() {
	// Add all the Spring advisors found according to superclass rules.
	// 调用父类的查找方法,父类是对配置文件中的信息进行解析,在Spring2.0之前仅支持配置文件
	List<Advisor> advisors = super.findCandidateAdvisors();
	// Build Advisors for all AspectJ aspects in the bean factory.
	// 对注解形式进行解析
	if (this.aspectJAdvisorsBuilder != null) {
		advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
	}
	return advisors;
}

这里也会调用父类 AbstractAdvisorAutoProxyCreator 下的 findCandidateAdvisors 方法,不过父类中的方法是对配置文件进行解析处理的,而下面的 aspectJAdvisorsBuilder.buildAspectJAdvisors 则是对注解形式处理的,由于现在基本都使用注解形式,所以这里直接看注解形式的处理,进到 BeanFactoryAspectJAdvisorsBuilder 类下的buildAspectJAdvisors 方法中:

public List<Advisor> buildAspectJAdvisors() {
	//获取缓存中包含@Aspect注解的 BeanName,取之前缓存的数据
	List<String> aspectNames = this.aspectBeanNames;
	//如果缓存中不存在,则是第一次初始化
	if (aspectNames == null) {
		//加锁
		synchronized (this) {
			// 在获取一次缓存中的数据
			aspectNames = this.aspectBeanNames;
			// 判断是否还为空
			if (aspectNames == null) {
				//创建一个集合,存储解析后的 Advisor
				List<Advisor> advisors = new ArrayList<>();
				// 给 aspectNames 赋初始值
				aspectNames = new ArrayList<>();
				//获取所有的 beanName
				String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
						this.beanFactory, Object.class, true, false);
				// 遍历所有的 beanName
				for (String beanName : beanNames) {
					// 判断该依赖是否合法,如果不合法就直接跳过了
					if (!isEligibleBean(beanName)) {
						continue;
					}
					// We must be careful not to instantiate beans eagerly as in this case they
					// would be cached by the Spring container but would not have been weaved.
					// 检查bean的类型是否为空了
					Class<?> beanType = this.beanFactory.getType(beanName, false);
					// 如果bean的类型为空直接跳过了
					if (beanType == null) {
						continue;
					}
					//判断类上有无 @Aspect 注解
					if (this.advisorFactory.isAspect(beanType)) {
						//将 beanName 写入 aspectNames 集合中
						aspectNames.add(beanName);
						// 创建一个AspectMetadata,主要存储切面元数据,构造方法注入了 beanName 与 beanType
						AspectMetadata amd = new AspectMetadata(beanType, beanName);
						//判断切面的实例化模式
						if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
							//如果是SINGLETON模式的话
							//创建切面元数据的实例化工厂
							MetadataAwareAspectInstanceFactory factory =
									new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
							//进行解析,取出里面的增强方法
							List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
							//判断当前的beanName是不是单例的
							if (this.beanFactory.isSingleton(beanName)) {
								//如果是单例的,写入缓存,缓存的就是解析出来的增强方法
								//key 为beanName,value 为classAdvisors
								this.advisorsCache.put(beanName, classAdvisors);
							}
							else {
								// 不是单例
								// 缓存到切面工厂里
								// key 为beanName,value为 factory
								this.aspectFactoryCache.put(beanName, factory);
							}
							//将增强方法添加到 advisors 集合中
							advisors.addAll(classAdvisors);
						}
						//如果实例化代理不是SINGLETON方式
						else {
							// Per target or per this.
							// 判断当前beanName是否为单例模式
							if (this.beanFactory.isSingleton(beanName)) {
								//如果是则抛异常
								throw new IllegalArgumentException("Bean with name '" + beanName +
										"' is a singleton, but aspect instantiation model is not singleton");
							}
							//创建切面元数据工厂
							MetadataAwareAspectInstanceFactory factory =
									new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
							//存入切面工厂缓存中
							this.aspectFactoryCache.put(beanName, factory);
							//进行解析,取出里面的增强方法,并将增强方法添加到 advisors 集合中
							advisors.addAll(this.advisorFactory.getAdvisors(factory));
						}
					}
				}
				// 将带有 @Aspect 注解的 beanName 记到 aspectBeanNames 中
				this.aspectBeanNames = aspectNames;
				//返回解析出来的增强方法
				return advisors;
			}
		}
	}
	// aspectBeanNames 不为空,代表已经进行初始化过了,要考虑从缓存中取了

	//判断aspectNames是否为空
	if (aspectNames.isEmpty()) {
		//如果为空的话,代表没有切面,直接返回一个空集合
		return Collections.emptyList();
	}
	//如果aspectNames不为空
	//那么证明已经初始化过了,先考虑从缓存中取
	List<Advisor> advisors = new ArrayList<>();
	//遍历aspectNames里面所有的切面
	for (String aspectName : aspectNames) {
		//尝试从增强方法的缓存中取
		List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
		//如果增强方法的缓存中有
		//添加进返回集合里面
		if (cachedAdvisors != null) {
			advisors.addAll(cachedAdvisors);
		}
		//如果增强方法的缓存中没有
		else {
			//就会尝试从切面元数据实例工厂缓存里面去取
			//从缓存中取出切面元数据实例工厂
			MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
			//使用工厂来创建该切面的所有增强方法,然后添加进集合中去
			advisors.addAll(this.advisorFactory.getAdvisors(factory));
		}
	}
	//最终返回增强方法集合
	return advisors;
}

这个方法内容比较长,主要分了两个处理方向,第一个是缓存中不存在的情况,需要进行初始化,第二个是缓存中存在直接取数据使用,这里看到缓存中不存在的情况下:

首先对当前对象进行加锁,防止并发情况下 aspectBeanNames 出现线程安全问题。aspectBeanNames主要缓存包含@Aspect 注解的 BeanName

然后从 Spring IOC 工厂中获取所有的 beanName 信息,并通过工厂拿到相应的 Class 类型,通过 advisorFactory.isAspect 方法判断是否为 Aspect 类,其实就是判断类上是否带有 @Aspect 注解,逻辑如下:

在这里插入图片描述

如果存在就存入 aspectNames 缓存中,再向下主要看到 this.advisorFactory.getAdvisors 方法,是一个抽象方法,具体逻辑由子类实现,其作用是用来对每个 Class 进行解析,取出里面的增强方法也就是切面方法,并封装成 Advisor 形式,这里看到 ReflectiveAspectJAdvisorFactory 类下的 getAdvisors 方法中:

public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
	//获取 Class 类型
	Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
	//获取 beanName
	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);

	//使用集合存放增强方法
	List<Advisor> advisors = new ArrayList<>();
	// 反射获取aspectClass中的方法
	// 遍历获取到的方法
	for (Method method : getAdvisorMethods(aspectClass)) {
		// Prior to Spring Framework 5.2.7, advisors.size() was supplied as the declarationOrderInAspect
		// to getAdvisor(...) to represent the "current position" in the declared methods list.
		// However, since Java 7 the "current position" is not valid since the JDK no longer
		// returns declared methods in the order in which they are declared in the source code.
		// Thus, we now hard code the declarationOrderInAspect to 0 for all advice methods
		// discovered via reflection in order to support reliable advice ordering across JVM launches.
		// Specifically, a value of 0 aligns with the default value used in
		// AspectJPrecedenceComparator.getAspectDeclarationOrder(Advisor).
		// 检验这个方法是不是增强方法,如果是则将方法转化成Advisor
		Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
		//判断结果是否存在
		if (advisor != null) {
			//如果存在就添加进结果集合中
			advisors.add(advisor);
		}
	}

	// If it's a per target aspect, emit the dummy instantiating aspect.
	//如果结果集不为空,并且还配置了增强延迟初始化
	if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
		//去实例化一个同步实例增强器
		Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
		//添加进advisors结果集的第 0 个位置
		advisors.add(0, instantiationAdvisor);
	}

	// Find introduction fields.
	//获取aspectClass的所有被 @DeclaredParents 修饰的字段
	for (Field field : aspectClass.getDeclaredFields()) {
		//同样进行转化成Advisor对象,然后过滤掉一些不符合条件的字段
		Advisor advisor = getDeclareParentsAdvisor(field);
		//如果不为null,添加进结果集里面
		if (advisor != null) {
			advisors.add(advisor);
		}
	}
	//最终返回结果集
	return advisors;
}

首先获取到前面封装的 Class 类型和 beanName,下面使用反射获取到 Class 中的 Method,然后对获取到的 Method 使用 getAdvisor 方法检验是不是增强方法也就是切面方法,如果是话则包装成 Advisor 类型,下面看到 getAdvisor 方法中:

public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
		int declarationOrderInAspect, String aspectName) {
	//对标识的类进行校验
	validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());

	//获取切点表达式,如果具有切点表达式,才算合法的 通知器,否则不合法
	AspectJExpressionPointcut expressionPointcut = getPointcut(
			candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
	//判断切入点是否为空
	if (expressionPointcut == null) {
		//如果没有切入点,直接返回null
		return null;
	}
	//如果有切入点,就根据切点信息生成增强器
	return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
			this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}

这里再次对标识的类进行校验,比如看类上是否还带有@Aspect注解等,下面则调用 getPointcut 方法获取到 一个 AspectJExpressionPointcut对象,其作用主要是判断 Method 是否是切面方法,如果是则封装成 AspectJExpressionPointcut 对象,AspectJExpressionPointcut 从命名就可以看出和 Expression 有关 ,主要用来对切点表达式的解析和匹配,下面在匹配切面方法时会使用到该类。

下面看到 getPointcut 方法:

private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
	//寻找方法上有无对应的注解
	AspectJAnnotation<?> aspectJAnnotation =
			AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
	//判断有没有匹配的注解
	if (aspectJAnnotation == null) {
		//没有匹配的注解直接返回Null,
		return null;
	}
	//使用 AspectJExpressionPointCut 来封装数据
	AspectJExpressionPointcut ajexp =
			new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
	// 注入切入点的表达式,也就是规则拦截的表达式
	ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
	if (this.beanFactory != null) {
		//注入beanFactory
		ajexp.setBeanFactory(this.beanFactory);
	}
	return ajexp;
}

第一步通过 AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod 寻找有无对应的注解,进到该方法中:

protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
	//遍历要匹配的注解,分别会处理: @Pointcut, @Around, @Before, @After, @AfterReturning, @AfterThrowing注解
	for (Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) {
		// 查找是否有当前注解
		AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz);
		//如果有就直接返回,可以看到如果给方法加上了多个注解,会根据 ASPECTJ_ANNOTATION_CLASSES 中的顺序前面的生效
		if (foundAnnotation != null) {
			return foundAnnotation;
		}
	}
	return null;
}

遍历了 ASPECTJ_ANNOTATION_CLASSES 数组,该数组的内容如下:

在这里插入图片描述

其实就是挨个判断是否是 Aspect 中的注解,如果有包装成 AspectJAnnotation 对象返回,这里看到 findAnnotation 方法中是如何判断的:

private static <A extends Annotation> AspectJAnnotation<A> findAnnotation(Method method, Class<A> toLookFor) {
	// 查找注解
	A result = AnnotationUtils.findAnnotation(method, toLookFor);
	if (result != null) {
		return new AspectJAnnotation<>(result);
	}
	else {
		return null;
	}
}

使用 AnnotationUtils.findAnnotation 工具找寻对应的注解,如果存在则新建一个 AspectJAnnotation 对象,再看下 AspectJAnnotation 对象的构造方法中初始化可那些内容:

在这里插入图片描述

主要将切点表达式,以及 argNames 参数进行了保存,这里可以看下 debug 的内容:

在这里插入图片描述
就是 Aspect 类注解中配置的内容,再回到前面 getPointcut 方法中,第一步获取到注解信息后,如果存在则创建了一个 AspectJExpressionPointcut 对象,并将解析出来的 AspectJAnnotation 对象添加进去,同时也将Spring 工厂也添加进去,最后返回出去。

再回到 getAdvisor 方法中,获取到 AspectJExpressionPointcut 对象后,如果不为空就新建一个 InstantiationModelAwarePointcutAdvisorImpl 实例,该实例是 Advisor 的子类。

这里简单介绍下 Advisor ,它通常与Pointcut 和 Advice 组合使用,Pointcut 用于定义切入点,即确定需要被增强的代码位置。而 Advice 则是实际的增强逻辑,它可以在目标代码执行前、执行后或出现异常时进行增强。Advisor 则是将 Pointcut 和 Advice 进行组合的组件

这里看到 InstantiationModelAwarePointcutAdvisorImpl 的构造方法中:

public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
		Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
		MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
	// 当前的切点表达式
	this.declaredPointcut = declaredPointcut;
	// 切面的 Class
	this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
	// 切面方法的名称
	this.methodName = aspectJAdviceMethod.getName();
	// 切面方法的参数类型
	this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
	// 切面方法
	this.aspectJAdviceMethod = aspectJAdviceMethod;
	// aspect 通知工厂
	this.aspectJAdvisorFactory = aspectJAdvisorFactory;
	// aspect 实例工厂
	this.aspectInstanceFactory = aspectInstanceFactory;
	// 切面的顺序
	this.declarationOrder = declarationOrder;
	// 切面的名称
	this.aspectName = aspectName;

	// 如果配置了增强延迟初始化
	if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
		// Static part of the pointcut is a lazy type.
		// 切入点的静态部分是一个惰性类型
		Pointcut preInstantiationPointcut = Pointcuts.union(
				aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);

		// Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
		// If it's not a dynamic pointcut, it may be optimized out
		// by the Spring AOP infrastructure after the first evaluation.
		this.pointcut = new PerTargetInstantiationModelPointcut(
				this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
		this.lazy = true;
	}
	else {
		// A singleton aspect.
		this.pointcut = this.declaredPointcut;
		this.lazy = false;
		// 非懒加载,直接初始化
		this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
	}
}

可以看到包含了切点表达式以及切面类信息,再下面判断是否为懒加载情况,如果不是则使用 instantiateAdvice 进行初始化 Advice,前面提到 Advice 就是实际的增强逻辑,也就是切面方法,看到 instantiateAdvice 方法中:

private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
	//调用 aspectAdvisorFactory 来获取增强器
	Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
			this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
	return (advice != null ? advice : EMPTY_ADVICE);
}

调用了 aspectJAdvisorFactory.getAdvice 方法来获得 Advice ,再看到该方法下:

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

	//获取切面的class
	Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
	//校验
	validate(candidateAspectClass);

	//获取方法上的注解
	AspectJAnnotation<?> aspectJAnnotation =
			AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
	if (aspectJAnnotation == null) {
		return null;
	}

	// If we get here, we know we have an AspectJ method.
	// Check that it's an AspectJ-annotated class
	if (!isAspect(candidateAspectClass)) {
		throw new AopConfigException("Advice must be declared inside an aspect type: " +
				"Offending method '" + candidateAdviceMethod + "' in class [" +
				candidateAspectClass.getName() + "]");
	}

	if (logger.isDebugEnabled()) {
		logger.debug("Found AspectJ method: " + candidateAdviceMethod);
	}

	//AbstractAspectJAdvice 其实就是增强器的一个抽象模板
	AbstractAspectJAdvice springAdvice;
	//对注解的类型进行判断
	switch (aspectJAnnotation.getAnnotationType()) {
		//如果是@PointCut类型
		case AtPointcut:
			if (logger.isDebugEnabled()) {
				logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
			}
			//@PointCut类型没有增强器,其代表的仅仅只是一个切入点
			return null;
		//如果是@Around类型
		case AtAround:
			//返回一个AspectJAroundAdvice
			springAdvice = new AspectJAroundAdvice(
					candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
			break;
		//如果是@Before类型
		case AtBefore:
			//返回一个AspectJMethodBeforeAdvice
			springAdvice = new AspectJMethodBeforeAdvice(
					candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
			break;
		//如果是@After类型
		case AtAfter:
			//返回一个AspectJAfterAdvice
			springAdvice = new AspectJAfterAdvice(
					candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
			break;
		//如果是一个@AfterReturning注解
		case AtAfterReturning:
			//返回一个AspectJAfterReturingAdvice
			springAdvice = new AspectJAfterReturningAdvice(
					candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
			//获取@AfterReturing的属性
			AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
			//判断是否为空,不为空就添加进springAdvice中
			//这里对应的属性是returningName
			if (StringUtils.hasText(afterReturningAnnotation.returning())) {
				springAdvice.setReturningName(afterReturningAnnotation.returning());
			}
			break;
		//判断是不是@AfterThrowing注解
		case AtAfterThrowing:
			//返回一个AspectJAfterThrowingAdvice
			springAdvice = new AspectJAfterThrowingAdvice(
					candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
			//获取@AfterThrowing注解上的属性
			AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
			//判断是否为空,不为空就添加进springAdvice中
			//这里对应的属性是throwingName,
			if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
				springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
			}
			break;
		//如果不是上面的5种类型,抛错处理
		default:
			throw new UnsupportedOperationException(
					"Unsupported advice type on method: " + candidateAdviceMethod);
	}

	// Now to configure the advice...
	//接下来给建言添加一些配置
	//注入切入的名称
	springAdvice.setAspectName(aspectName);
	springAdvice.setDeclarationOrder(declarationOrder);
	String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
	if (argNames != null) {
		springAdvice.setArgumentNamesFromStringArray(argNames);
	}
	springAdvice.calculateArgumentBindings();

	return springAdvice;
}

这里对不同类型的 Aspect 注解进行判断,生成不同的 AbstractAspectJAdvice 增强包装类,AbstractAspectJAdvice 是 Advice 的一个子类,这里以 @Before类型为例,可以看下 AspectJMethodBeforeAdvice 类的实现:

在这里插入图片描述

上一步生成对应的 AbstractAspectJAdvice 增强实例后,在回到前面的 getAdvisor 方法中也就是已经声明好了 InstantiationModelAwarePointcutAdvisorImpl Advisor 实例,再回到 getAdvisors 方法中,将获取到的 Advisor 实例放入了 advisors 集合中,最后返回给了前面的 buildAspectJAdvisors 方法中,接着判断如果是单例的话就将结果缓存下来,便于下次使用,最后在将结果返回给 findEligibleAdvisors 方法中。

在 findEligibleAdvisors 方法中,通过 findCandidateAdvisors 方法已经获取到了所有的增强方法,下面使用 findAdvisorsThatCanApply 进行匹配找出适合该 bean 的增强方法。

四、 匹配 Aspect 切面方法

进到 findAdvisorsThatCanApply 方法中:

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

	ProxyCreationContext.setCurrentProxiedBeanName(beanName);
	try {
		return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
	}
	finally {
		ProxyCreationContext.setCurrentProxiedBeanName(null);
	}
}

第一步现将 beanName 记入ThreadLocal 中标记当前正在匹配的 beanName,然后触发 AopUtils.findAdvisorsThatCanApply 方法进行匹配,看到该方法下:

public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
	if (candidateAdvisors.isEmpty()) {
		return candidateAdvisors;
	}
	// 创建一个合适的 Advisor 的集合 eligibleAdvisors
	List<Advisor> eligibleAdvisors = new ArrayList<>();
	//循环所有的Advisor
	for (Advisor candidate : candidateAdvisors) {
		// 判断切面是否匹配
		//如果Advisor是 IntroductionAdvisor 引介增强 可以为目标类 通过AOP的方式添加一些接口实现
		if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
			eligibleAdvisors.add(candidate);
		}
	}
	//是否有引介增强
	boolean hasIntroductions = !eligibleAdvisors.isEmpty();
	for (Advisor candidate : candidateAdvisors) {
		//如果是IntroductionAdvisor类型的话 则直接跳过
		if (candidate instanceof IntroductionAdvisor) {
			// already processed
			continue;
		}
		// 判断切面是否匹配
		if (canApply(candidate, clazz, hasIntroductions)) {
			eligibleAdvisors.add(candidate);
		}
	}
	return eligibleAdvisors;
}

这里逻辑主要分了两个方向是否为 IntroductionAdvisor 引介增强器,引介增强可以为目标类通过AOP的方式添加一些接口实现,也就是使用 @DeclareParents 注解的情况下,前面我们分析的 Advisor 类型为InstantiationModelAwarePointcutAdvisorImpl ,这里也主要看下这种类型下的匹配过程,看下该类的继承关系:

在这里插入图片描述
属于 PointcutAdvisor 类型的 Advisor ,因此会通过 canApply 方法判断是否匹配,继续看到 canApply 方法中:

public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
	if (advisor instanceof IntroductionAdvisor) {
		// IntroductionAdvisor,根据类过滤器,进行匹配
		//如果是 IntroductionAdvisor 的话,则调用IntroductionAdvisor类型的实例进行类的过滤
		//这里是直接调用的ClassFilter的matches方法
		return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
	}
	// 通常情况下 Advisor 都是 PointcutAdvisor 类型
	else if (advisor instanceof PointcutAdvisor) {
		PointcutAdvisor pca = (PointcutAdvisor) advisor;
		// 从Advisor中获取Pointcut的实现类 就是是AspectJExpressionPointcut
		return canApply(pca.getPointcut(), targetClass, hasIntroductions);
	}
	else {
		// It doesn't have a pointcut so we assume it applies.
		return true;
	}
}

这里又进行了类型判断,上面已经看到InstantiationModelAwarePointcutAdvisorImpl 属于 PointcutAdvisor 类型的 Advisor,因此再看到 canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) 方法中,注意 Pointcut 参数传递的 pca.getPointcut() 在声明 InstantiationModelAwarePointcutAdvisorImpl 下,其实就是 AspectJExpressionPointcut :

public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
	Assert.notNull(pc, "Pointcut must not be null");

	//进行切点表达式的匹配最重要的就是 ClassFilter 和 MethodMatcher这两个方法的实现。
	//首先进行ClassFilter的matches方法校验
	//首先这个类要在所匹配的规则下
	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;
	}
	// 如果当前 MethodMatcher 也是IntroductionAwareMethodMatcher类型,则转为该类型
	IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
	if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
		introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
	}

	Set<Class<?>> classes = new LinkedHashSet<>();
	if (!Proxy.isProxyClass(targetClass)) {
		// 目标对象没有采用jdk动态代理,则要么是cglib代理,要么没有代理,获取到没有代理的原始类
		classes.add(ClassUtils.getUserClass(targetClass));
	}
	// 获取到目标类的所有的超类接口
	classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));

	for (Class<?> clazz : classes) {
		// 获取目标类即接口的方法,只要有一个方法满足切点条件,即视为切点可以匹配
		Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
		// 只要有一个方法能匹配到就返回true
		//MethodMatcher 中有两个 matches 方法。
		// boolean matches(Method method, Class<?> targetClass) 用于静态的方法匹配
		// boolean matches(Method method, Class<?> targetClass, Object... args) 用于运行期动态的进行方法匹配
		for (Method method : methods) {
			// 如果 MethodMatcher 是IntroductionAwareMethodMatcher类型,则使用该类型的方法进行匹配
			// 否则使用 MethodMatcher.matches() 方法进行匹配
			if (introductionAwareMethodMatcher != null ?
					introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
					methodMatcher.matches(method, targetClass)) {
				return true;
			}
		}
	}

	return false;
}

这里首先通过 pc.getClassFilter().matches 方法进行匹配,其中 getClassFilter() 方法就是 AspectJExpressionPointcut 类下的 getClassFilter() 方法:

public ClassFilter getClassFilter() {
	obtainPointcutExpression();
	return this;
}

最后返回的就是自己,也就是调用了 AspectJExpressionPointcut 类下的 matches(Class<?> targetClass) 进行判断的,这里先看下 obtainPointcutExpression() 方法中做了什么:

private PointcutExpression obtainPointcutExpression() {
	if (getExpression() == null) { //表达式不存在,直接抛出异常
		throw new IllegalStateException("Must set property 'expression' before attempting to match");
	}
	if (this.pointcutExpression == null) {
		// 确认类加载器
		this.pointcutClassLoader = determinePointcutClassLoader();
		// 创建切点表达式
		this.pointcutExpression = buildPointcutExpression(this.pointcutClassLoader);
	}
	return this.pointcutExpression;
}

其实是生成了一个切点表达式解析器,注意这个切点表达式解析器不是Spring提供的,是采用的 aspectj 包提供的PointcutExpression ,关于 PointcutExpression 这里不做过多的介绍了,下面主要看到 obtainPointcutExpression() 是怎么创建切点表达式解析器的:

private PointcutExpression buildPointcutExpression(@Nullable ClassLoader classLoader) {
	// 初始化切点解析器
	PointcutParser parser = initializePointcutParser(classLoader);
	PointcutParameter[] pointcutParameters = new PointcutParameter[this.pointcutParameterNames.length];
	for (int i = 0; i < pointcutParameters.length; i++) {
		pointcutParameters[i] = parser.createPointcutParameter(
				this.pointcutParameterNames[i], this.pointcutParameterTypes[i]);
	}
	// 使用切点解析器进行解析表达式获取切点表达式
	return parser.parsePointcutExpression(replaceBooleanOperators(resolveExpression()),
			this.pointcutDeclarationScope, pointcutParameters);
}

第一步初始化了切点解析器,看到 initializePointcutParser 方法中,如何操作的:

private PointcutParser initializePointcutParser(@Nullable ClassLoader classLoader) {
	// 获得切点解析器
	PointcutParser parser = PointcutParser
			.getPointcutParserSupportingSpecifiedPrimitivesAndUsingSpecifiedClassLoaderForResolution(
					SUPPORTED_PRIMITIVES, classLoader);
	parser.registerPointcutDesignatorHandler(new BeanPointcutDesignatorHandler());
	return parser;
}

通过 PointcutParser 获取了一个解析器,在回到上一步buildPointcutExpression方法中,这里将切点表达式填充到了切点解析器中生成 PointcutExpression 。

下面再看到 AspectJExpressionPointcut 下的 matches 方法:

public boolean matches(Class<?> targetClass) {
	PointcutExpression pointcutExpression = obtainPointcutExpression();
	try {
		try {
			// 使用切点表达式进行粗筛
			return pointcutExpression.couldMatchJoinPointsInType(targetClass);
		}
		catch (ReflectionWorldException ex) {
			logger.debug("PointcutExpression matching rejected target class - trying fallback expression", ex);
			// Actually this is still a "maybe" - treat the pointcut as dynamic if we don't know enough yet
			PointcutExpression fallbackExpression = getFallbackPointcutExpression(targetClass);
			if (fallbackExpression != null) {
				return fallbackExpression.couldMatchJoinPointsInType(targetClass);
			}
		}
	}
	catch (Throwable ex) {
		logger.debug("PointcutExpression matching rejected target class", ex);
	}
	return false;
}

第一步就是拿到上面已经生成的 PointcutExpression 切点表达式,然后通过 couldMatchJoinPointsInType 判断 targetClass 是否符合。

下面回到前面的 findAdvisorsThatCanApply 方法中,如果 canApply 方法返回 true 也标识匹配成功,就将这个 Advisor 放入 eligibleAdvisors 集合中,最终返回给前面的 findEligibleAdvisors 方法中,在该方法中如果匹配的 Advisor 存在的话排序出先顺序,最终给到 wrapIfNecessary 方法中。

(二) - 代理对象的创建以及执行过程

一、SpringAop 代理创建 以及 执行过程

在上篇文章中分析得出在使用 Aop 时,实际向 Spring 容器中注入了一个 AnnotationAwareAspectJAutoProxyCreator 动态代理 bean 生成处理器,该类有实现 BeanPostProcessor 扩展方法,并且在 postProcessAfterInitialization 进行了代理的创建,主要逻辑在 AbstractAutoProxyCreator 类下的 wrapIfNecessary 方法中,上篇文章主要分析的该方法下getAdvicesAndAdvisorsForBean 方法,主要做了对切面方法的扫描和匹配过程,并且这里拿到的结果就是所有匹配的切面方法包装类集合,本篇文章继续上篇文章的脚步,分析下后面代理对象的创建过程和执行过程。

下面是上篇文章的地址:

SpringAop 源码解析 (一) - Aspect 切面方法的查找匹配过程

二、动态代理类型的判断过程

在这里插入图片描述
上面文章分析到这个位置,下面继续,如果存在匹配的切面方法,则先进行标记,反之不存在也进行标记,下次再进来该 beanName 时,不存在就直接跳过了。

这里看到获取到匹配的切面方法后,通过 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();
	proxyFactory.copyFrom(this);

	if (!proxyFactory.isProxyTargetClass()) {
		if (shouldProxyTargetClass(beanClass, beanName)) {
			proxyFactory.setProxyTargetClass(true);
		}
		else {
			evaluateProxyInterfaces(beanClass, proxyFactory);
		}
	}

	Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
	proxyFactory.addAdvisors(advisors);
	proxyFactory.setTargetSource(targetSource);
	customizeProxyFactory(proxyFactory);

	proxyFactory.setFrozen(this.freezeProxy);
	if (advisorsPreFiltered()) {
		proxyFactory.setPreFiltered(true);
	}

	return proxyFactory.getProxy(getProxyClassLoader());
}

这里创建了一个代理工厂,并将切面方法、目标 bean 资源等,设置进入了该代理工厂中。

下面主要看到 proxyFactory.getProxy 又是如何创建代理对象的:

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

这里首先使用 createAopProxy 方法创建一个 AopProxy ,然后再通过AopProxy的 getProxy 生成代理对象。

这里先看到 createAopProxy 方法下,在 ProxyCreatorSupport 类中:

protected final synchronized AopProxy createAopProxy() {
	if (!this.active) {
		activate();
	}
	// 通过 aop动态代理工厂 创建 aop动态代理
	return getAopProxyFactory().createAopProxy(this);
}

这里通过 AopProxyFactory 中 createAopProxy 创建一个 AopProxy ,默认情况下 AopProxyFactory 的具体实现为 DefaultAopProxyFactory 类,在ProxyCreatorSupport 类的无参构造方法中进行初始化的。

在这里插入图片描述

下面看到 DefaultAopProxyFactory 类中的 createAopProxy 方法中:

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
	if (!IN_NATIVE_IMAGE &&
			(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.");
		}
		// 如果被代理对象是接口,则使用jdk动态代理
		if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
			return new JdkDynamicAopProxy(config);
		}
		// 如果被代理对象没有实现接口,则使用 cglib 动态代理
		return new ObjenesisCglibAopProxy(config);
	}
	else {
		// 当前环境是否是原生环境,原生环境,使用 jdk动态代理
		return new JdkDynamicAopProxy(config);
	}
}

这里判断目标类是否有实现接口,如果有的话则使用 JDK 的动态代理,否则的话使用 cglib 进行代理。

下面回到上面的 getProxy 方法中,createAopProxy() 方法生成的要么是JDK 的动态代理,要么是 cglib 的动态代理,这里首先看下 JDK 动态代理的创建过程。

三、JDK 动态代理创建过程

这里先分析下 JdkDynamicAopProxy 类

在这里插入图片描述
可以看到实现了 InvocationHandler 接口,因此在执行代理时,会触发该类下的 invoke 方法。

再看下 JdkDynamicAopProxy 类的构造方法中做了什么事情:

public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
	Assert.notNull(config, "AdvisedSupport must not be null");
	//判断增强器和拦截器的数量
	if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
		//如果为0就抛出异常
		throw new AopConfigException("No advisors and no TargetSource specified");
	}
	//注入配置
	this.advised = config;
	// 获取完整的代理接口,并进行缓存
	this.proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
	// 判断有没有定义的equals方法和hashCode方法
	findDefinedEqualsAndHashCodeMethods(this.proxiedInterfaces);
}

这里先判断增强器也就是切面方法是否存在,如果不存在代理也没有意义了,接着将配置注入到 advised 属性中,最后标记出被代理类是否有定义 equals 方法和 hashCode 方法。

下面再看到 getProxy 方法,如何生成代理对象的:

public Object getProxy(@Nullable ClassLoader classLoader) {
	if (logger.isTraceEnabled()) {
		logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
	}
	// 通过JDK 的 Proxy完成动态代理
	return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
}

直接通过 Proxy.newProxyInstance 创建代理实例,并且 InvocationHandler 就是自己,也就是触发执行代理时会触发该类下的 invoke 方法。

四、JDK 动态代理执行过程

JDK 动态代理执行,直接看到动态的代理的 invoke 方法中

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

	// 获取被代理对象的类信息
	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.
			// 如果被代理对象没有重写 equals方法,则调用本地的方法。 比较的是被代理对象
			return equals(args[0]);
		}
		else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
			// The target does not implement the hashCode() method itself.
			// 如果被代理对象没有重写 hashCode 方法,则调用本地的 hashCode 方法。
			return hashCode();
		}
		else if (method.getDeclaringClass() == DecoratingProxy.class) {
			// There is only getDecoratedClass() declared -> dispatch to proxy config.
			// 如果实现了 DecoratingProxy的方法,则 分发给代理配置
			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...
			// 使用代理配置在ProxyConfig上调用服务
			return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
		}

		// 实际方法的返回值
		Object retVal;

		// 如果需要暴露至 threadLocal,则进行暴露
		// 目的是在同一个类中自我方法调用的情况下
		// 由于执行问题 被调用的无法执行代理
		// 因此可以通过配置 exposeProxy 为 true,将代理方法缓存到 threadLocal 中
		if (this.advised.exposeProxy) {
			// Make invocation available if necessary.
			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);

		// Get the interception chain for this method.
		// 获取被代理类的当前方法的增强器链
		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.
			Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
			retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
		}
		else {
			// We need to create a method invocation...
			// 根据切面的配置,构造方法执行链
			MethodInvocation invocation =
					new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
			// Proceed to the joinpoint through the interceptor 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;
		}
		//如果返回值为null,并且返回类型不是void类型,并且返回类型还被定义为基本数据类型
		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);
		}
		//如果暴露过proxyContext
		if (setProxyContext) {
			// Restore old proxy.
			// 恢复为原始的proxy
			AopContext.setCurrentProxy(oldProxy);
		}
	}
}

这里讲下 this.advised.exposeProxy 的作用,该值就是使用 @EnableAspectJAutoProxy 注解中的 exposeProxy 参数,如果是 true 的话,则会对当前代理对象进行缓存,目的是在同一个类中自我方法调用的情况下,如果被调用的方法带有 @Transactional 或 @Async 等注解,直接调用方法注解会失效,因为指向的是this指针,并不是代理类,因此可以设置 exposeProxy 参数为true,将代理类缓存下来,自我调用时使用 AopContext.currentProxy() 获取到当前的代理对象,例如下面的案例:

@Component
public class TestAop {

    public void test(){
        System.out.println("test...");
        // 自我调用
        ((TestAop) AopContext.currentProxy()).test2();
    }

    @Transactional
    public void test2(){
        System.out.println("test2");
    }
}

这里的缓存其实就是使用的 ThreadLocal 进行的存储:

在这里插入图片描述

在继续看 invoke 方法,下面使用 this.advised.getInterceptorsAndDynamicInterceptionAdvice 生成所有匹配的切面方法的执行链,下面看到该方法中:

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

这里会对执行链进行缓存,这里看下缓存中不存在时,调用的 this.advisorChainFactory.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();
	// 从动态代理配置中,获取 通知器列表
	Advisor[] advisors = config.getAdvisors();
	List<Object> interceptorList = new ArrayList<>(advisors.length);
	Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
	Boolean hasIntroductions = null;

	// 遍历通知器
	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) {
							// 当切面匹配器已经在工作时,则放入 InterceptorAndDynamicMethodMatcher,运行时匹配
							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;
}

在该方法中,获取到之前匹配出来的切面方法,再次进行筛选匹配。

下面再回到 invoke 方法中,接着向下看如果执行链为空则直接使用 AopUtils.invokeJoinpointUsingReflection 方法触发目标方法,逻辑如下:

public static Object invokeJoinpointUsingReflection(@Nullable Object target, Method method, Object[] args)
		throws Throwable {

	// Use reflection to invoke the method.
	try {
		ReflectionUtils.makeAccessible(method);
		return method.invoke(target, args);
	}
	catch (InvocationTargetException ex) {
		// Invoked method threw a checked exception.
		// We must rethrow it. The client won't see the interceptor.
		throw ex.getTargetException();
	}
	catch (IllegalArgumentException ex) {
		throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" +
				method + "] on target [" + target + "]", ex);
	}
	catch (IllegalAccessException ex) {
		throw new AopInvocationException("Could not access method [" + method + "]", ex);
	}
}

如果执行链存在,则根据切面的配置,构造一个 ReflectiveMethodInvocation 切面方法的执行链,执行链中包含了切面方法、目标方法、目标对象等:

protected ReflectiveMethodInvocation(
		Object proxy, @Nullable Object target, Method method, @Nullable Object[] arguments,
		@Nullable Class<?> targetClass, List<Object> interceptorsAndDynamicMethodMatchers) {

	this.proxy = proxy;
	this.target = target;
	this.targetClass = targetClass;
	this.method = BridgeMethodResolver.findBridgedMethod(method);
	this.arguments = AopProxyUtils.adaptArgumentsIfNecessary(method, arguments);
	// 拦截器的动态方法匹配器
	this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers;
}

再向下看则调用了 invocation.proceed() ,其实是触发所有的切面增强方法,最后再触发目标方法,看到 ReflectiveMethodInvocation 类中,逻辑如下:

public Object proceed() throws Throwable {
	// 该方法为 jdk的AOP实现的核心
	// We start with an index of -1 and increment early.
	// 从拦截器链条的尾部向头部进行递归执行
	if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
		return invokeJoinpoint();
	}
	// 获取下一个要执行的拦截器
	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);
		}
		//如果动态匹配失败,递归进行proceed
		//不匹配就不执行当前的拦截器
		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);
	}
}

这里使用 currentInterceptorIndex 变量表示当前触发的第几个切面增强方法,首先判断的当 currentInterceptorIndex 等于interceptorsAndDynamicMethodMatchers 最后一个时,就是代表所有的切面方法都触发完了,这里的 invokeJoinpoint() 等一会再看。

先来看
((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this) 是如何触发的目标切面方法,这里可以看到实现有很多种:

在这里插入图片描述

这里还是以 MethodBeforeAdviceInterceptor 为例,表示 @Before 前置通知方法:

public Object invoke(MethodInvocation mi) throws Throwable {
	this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
	// 继续触发下一个
	return mi.proceed();
}

这里通过 this.advice.before 触发前置通知方法后,又递归的方式触发下一个切面增强方法。这里看下 this.advice.before怎么触发的前置通知方法:

在这里插入图片描述在这里插入图片描述
最终触发的是 invokeAdviceMethodWithGivenArgs 方法,逻辑如下:

protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
	//对参数处理
	Object[] actualArgs = args;
	if (this.aspectJAdviceMethod.getParameterCount() == 0) {
		actualArgs = null;
	}
	try {
		//下面就是通过反射来调用方法了
		//先让方法变得可以访问
		ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
		// TODO AopUtils.invokeJoinpointUsingReflection
		//使用切面实例共产获取切面实例,然后执行建言方法
		return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
	}
	catch (IllegalArgumentException ex) {
		throw new AopInvocationException("Mismatch on arguments to advice method [" +
				this.aspectJAdviceMethod + "]; pointcut expression [" +
				this.pointcut.getPointcutExpression() + "]", ex);
	}
	catch (InvocationTargetException ex) {
		throw ex.getTargetException();
	}
}

通过反射直接触发目标切面方法。

下面再回到 proceed() 方法中,当执行完所有的切面方法后会触发 invokeJoinpoint 方法:

在这里插入图片描述
这里和前面无执行链时调用逻辑一样,使用AopUtils.invokeJoinpointUsingReflection 方法触发目标方法。

五、cglib 动态代理创建过程

cglib 动态代理和 JDK动态代理实现逻辑大致相同,这里还是先看下继承关系:
在这里插入图片描述
继承了 CglibAopProxy ,主要代理创建的逻辑其实都在 CglibAopProxy 中,构造方法也是调用了父类的构造方法中:

public CglibAopProxy(AdvisedSupport config) throws AopConfigException {
	Assert.notNull(config, "AdvisedSupport must not be null");
	if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
		throw new AopConfigException("No advisors and no TargetSource specified");
	}
	this.advised = config;
	this.advisedDispatcher = new AdvisedDispatcher(this.advised);
}

同样也是将配置注入到 advised 属性中,下面主要看到 getProxy 方法 中:

public Object getProxy(@Nullable ClassLoader classLoader) {
	if (logger.isTraceEnabled()) {
		logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
	}

	try {
		// 获取需要被代理的对象
		Class<?> rootClass = this.advised.getTargetClass();
		Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

		Class<?> proxySuperClass = rootClass;
		// 如果已经被代理过,则获取原始对象
		if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
			proxySuperClass = rootClass.getSuperclass();
			Class<?>[] additionalInterfaces = rootClass.getInterfaces();
			// 将原始类需要被实现的接口进行重写
			for (Class<?> additionalInterface : additionalInterfaces) {
				this.advised.addInterface(additionalInterface);
			}
		}

		// Validate the class, writing log messages as necessary.
		// 对类进行合法性验证
		validateClassIfNecessary(proxySuperClass, classLoader);

		// Configure CGLIB Enhancer...
		// 创建 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.
		// 创建cglib动态代理实例
		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);
	}
}

这里主要声明了 cglib 中的 Enhancer 实例,并填充代理的信息,其中创建代理对象在 createProxyClassAndInstance 方法中:

protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
	enhancer.setInterceptDuringConstruction(false);
	enhancer.setCallbacks(callbacks);
	return (this.constructorArgs != null && this.constructorArgTypes != null ?
			enhancer.create(this.constructorArgTypes, this.constructorArgs) :
			enhancer.create());
}

六、cglib 动态代理执行过程

在 JDK 动态代理时,触发代理类时会触发 invoke 方法,同样在 cglib 代理中,触发代理类时,会触发 Enhancer中 callbacks 类中的 intercept 方法,下面就从 callbacks 开始分析:

在前一步创建代理时 callbacks 就是通过 getCallbacks 方法获取的结果,下面看到该方法下:

private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
	// Parameters used for optimization choices...
	//判断是不是要进行曝光
	boolean exposeProxy = this.advised.isExposeProxy();
	boolean isFrozen = this.advised.isFrozen();
	boolean isStatic = this.advised.getTargetSource().isStatic();

	// Choose an "aop" interceptor (used for AOP calls).
	// 创建 cgLib 层面的动态切面拦截器,动态代理通过它完成
	Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);

	// Choose a "straight to target" interceptor. (used for calls that are
	// unadvised but can return this). May be required to expose the proxy.
	Callback targetInterceptor;

	//判断是否要曝光
	//根据是否要曝光并且是动态代理还是静态代理去生成拦截器
	//这里的targetInterceptor拦截器称为目标拦截器
	//这个拦截器的作用实质上没有对方法进行增强,但里面的额外操作会将当前代理对象切面曝光出来
	//Cglib还支持静态代理咧。。。
	if (exposeProxy) {
		//如果要曝光,对应要创建exposedInterceptor
		//并且从创建方法可以看到,直接给了目标对象,并没有给增强器
		//在这里exposedInterceptor是会对代理对象进行曝光的
		targetInterceptor = (isStatic ?
				new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
				new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));
	}
	else {
		//如果不需要曝光,创建unadvvisedInterceptor,从名字就可以看出,是一个没有增强器的拦截器
		//但其实还会对返回值做一些处理
		targetInterceptor = (isStatic ?
				new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
				new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));
	}

	// Choose a "direct to target" dispatcher (used for
	// unadvised calls to static targets that cannot return this).
	// 创建targetDispatcher,这个跟unadvisedInterceptor的作用其实差不多
	// 直接执行目标对象的方法,本质上没有做其他任何其他增强操作,不过可能会对返回值做一些处理
	Callback targetDispatcher = (isStatic ?
			new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());

	// 将切面包装成拦截器链
	Callback[] mainCallbacks = new Callback[] {
			aopInterceptor,  // for normal advice
			targetInterceptor,  // invoke target without considering advice, if optimized
			new SerializableNoOp(),  // no override for methods mapped to this
			targetDispatcher, this.advisedDispatcher,
			new EqualsInterceptor(this.advised),
			new HashCodeInterceptor(this.advised)
	};

	Callback[] callbacks;

	// If the target is a static one and the advice chain is frozen,
	// then we can make some optimizations by sending the AOP calls
	// direct to the target using the fixed chain for that method.、
	//如果目标对象是静态的或者拦截器链是冻结的
	//这里会做一些修复措施
	if (isStatic && isFrozen) {
		Method[] methods = rootClass.getMethods();
		Callback[] fixedCallbacks = new Callback[methods.length];
		this.fixedInterceptorMap = CollectionUtils.newHashMap(methods.length);

		// TODO: small memory optimization here (can skip creation for methods with no advice)
		//遍历目标对象类型的所有方法
		for (int x = 0; x < methods.length; x++) {
			//当前的方法
			Method method = methods[x];
			//获取目标当前的方法需要执行的拦截器链,每个方法要进行的拦截器链都不一样
			List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, rootClass);
			//封装成FixedChainStaticTargetInterceptor存放进fixedCallBacks中
			fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
					chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
			this.fixedInterceptorMap.put(method, x);
		}

		// Now copy both the callbacks from mainCallbacks
		// and fixedCallbacks into the callbacks array.
		//将三个callBacks都集合起来
		callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
		System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
		System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
		this.fixedInterceptorOffset = mainCallbacks.length;
	}
	else {
		callbacks = mainCallbacks;
	}
	return callbacks;
}

这里对切面增强方法生成了一个 DynamicAdvisedInterceptor 下面主要看下 DynamicAdvisedInterceptor 中的 intercept 方法:

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 {
		// 如果需要暴露至 threadLocal,则进行暴露
		// 目的是在同一个类中自我方法调用的情况下
		// 由于执行问题 被调用的无法执行代理
		// 因此可以通过配置 exposeProxy 为 true,将代理方法缓存到 threadLocal 中
		if (this.advised.exposeProxy) {
			// Make invocation available if necessary.
			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代理时的大致相同,如果 exposeProxy 为true,就缓存暴露至threadLocal中,同样使用 this.advised.getInterceptorsAndDynamicInterceptionAdvice 生成切面增强方法链。

最后 proceed() 方法同样是触发的父类的方法,和 JDK 代理执行了相同的 proceed() 方法:

public Object proceed() throws Throwable {
	try {
		return super.proceed();
	}
	catch (RuntimeException ex) {
		throw ex;
	}
	catch (Exception ex) {
		if (ReflectionUtils.declaresException(getMethod(), ex.getClass())) {
			throw ex;
		}
		else {
			throw new UndeclaredThrowableException(ex);
		}
	}
}

 

posted @ 2024-12-12 09:15  CharyGao  阅读(23)  评论(0编辑  收藏  举报