Spring AOP源码解读(@Aspect注解)

Spring AOP的介绍:

什么是Spring AOP:
面向切面编程,基于动态代理实现的,如果动态代理不了解的,可以翻阅我其它的博客;也就是在执行方法前、方法后和出现异常后做拦截或者做增强处理,我们常用的使用方式就是@AspectJ注解、自己可以使用spring后置处理器自己来实现或者通过实现接口的方式、XML配置的方式;

AOP与AspectJ的关系:
Aspect属于Eclipse基金会,增强的方式是静态织入,它是通过修改代码来实现的,要使用它还要使用它特定的编译器;
SringAO和AspectJ没有什么关系,只是使用了AspectJ的一些概念,用到了其切点解析和匹配。

Spring Aop的发展:
Spring 3.2 以后,spring-core 直接就把 CGLIB 和 ASM 的源码包括进来了,这样在使用CGLB代理是不需要显示的引入这两个依赖。

  • Spring 1.2 基于接口的配置:最早的 Spring AOP 是完全基于几个接口的,想看源码的同学可以从这里起步。
  • Spring 2.0 schema-based 配置:Spring 2.0 以后使用 XML 的方式来配置,使用 命名空间
  • Spring 2.0 @AspectJ 配置:使用注解的方式来配置,这种方式感觉是最方便的,还有,这里虽然叫 做@AspectJ,但是这个和 AspectJ 其实没啥关系。

先来介绍Spring 1.2中基于接口的Aop ,直接上代码,不做介绍了,因为太简单了。
定义advice和intercepter:

public class MyLogAdvice implements MethodBeforeAdvice {
	@Override
	public void before(Method method, Object[] args, Object target) throws Throwable {
		//Object invoke = method.invoke(target, args);
		String name = method.getName();
		System.out.println("执行目标方法:"+name+"的前置通知,入参为:"+ Arrays.asList(args));
	}
}
public class MyInterceptor implements MethodInterceptor {
	@Override
	public Object invoke(MethodInvocation invocation) throws Throwable {
		Method method = invocation.getMethod();
		System.out.println("执行目标方法前置通知:"+method.getName());
		Object proceed = invocation.proceed();
		System.out.println("执行目标方法后置置通知:"+method.getName());
		return proceed;
	}
}
定义一个目标方法:

```java
@Component
public class MyCalculate implements Calculate {
	private int num = 0;

	public int getNum() {
		return num;
	}

	public void setNum(int num) {
		this.num = num;
	}

	@Override
	public int add(int numA, int numB) {
		System.out.println("执行目标方法:add");
		//1 / 0
		return numA + numB;
	}

	@Override
	public int sub(int numA, int numB) {
		System.out.println("执行目标方法:sub");
		return numA - numB;
	}
}

加入到容器中

@Bean
	public Calculate calculate() {
		return new MyCalculate();
	}

	@Bean
	public MethodBeforeAdvice myLogAdvice() {
		return new MyLogAdvice();
	}
	
	@Bean
	public MyInterceptor myInterceptor() {
		return new MyInterceptor();
	}

然后利用FactoryBean创建代理类;

	@Bean
	public ProxyFactoryBean proxyFactoryBean() {
		ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();
		proxyFactoryBean.setInterceptorNames("myLogAdvice","myInterceptor");
		proxyFactoryBean.setTarget(calculate());
		return proxyFactoryBean;
	}

执行一下

	AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AopConfig.class);
		Calculate calculate = context.getBean("proxyFactoryBean",Calculate.class);
		//calculate.sub(7, 8);
		calculate.add(1, 2);

结果为:Spring AOP源码解读(@Aspect注解)
从结果看,使用了责任链的方式对advice和Intercept都进行了调用,使用了FactoryBean的getObject方法创建一个代理类实现的。

下面介绍Advisor,它包含了advice增强和porintCut切点。Advisor有好几个实现类,比如NameMatchMethodPointcutAdvisor

	@Bean
	public NameMatchMethodPointcutAdvisor nameMatchMethodPointcutAdvisor(){
		NameMatchMethodPointcutAdvisor advisor = new NameMatchMethodPointcutAdvisor();
		advisor.setAdvice(myLogAdvice());
		advisor.setMappedName("add");
		return advisor;
	}
@Bean
	public ProxyFactoryBean proxyFactoryBean() {
		ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();
		proxyFactoryBean.setInterceptorNames("nameMatchMethodPointcutAdvisor");
		proxyFactoryBean.setTarget(calculate());
		return proxyFactoryBean;
	}

只对add方法进行拦截

自动生成代理类:BeanNameAutoProxyCreator

	@Bean
	public BeanNameAutoProxyCreator beanNameAutoProxyCreator() {
		BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator();
		beanNameAutoProxyCreator.setInterceptorNames("myLogAdvice");
		beanNameAutoProxyCreator.setBeanNames("calculate");
		return beanNameAutoProxyCreator;
	}

其实 Advisor 还有一个更加灵活的实现类 RegexpMethodPointcutAdvisor,它能实现正则匹配

DefaultAdvisorAutoProxyCreator,它的配置非常简单,直接使用下面这段配置就可以了,它 就会使得所有的 Advisor 自动生效,无须其他配置。(记得把之前的autoProxyCreator配置去掉,无需创建2次代理)

@Bean
	public DefaultAdvisorAutoProxyCreator autoProxyCreator(){
		return new DefaultAdvisorAutoProxyCreator();
	}

下面进入正题:Spring Aop @Aspect注解的源码解析

先上自己画的流程图:
Spring AOP源码解读(@Aspect注解)
直接上代码:不做过多解释,因为代码上都有注释:

使用AOP前要在配置类加上@EnableAspectJAutoProxy注解,其有proxyTargetClass属性,当为ture则强制使用CGLB,如果不设置默认为false,自己判断使用JDK还是CGLB,它的作用就是加入AOP代理对象的创建类AnnotationAwareAspectJAutoProxyCreator

因为Aop代理对象实现了后置处理器SmartInstantiationAwareBeanPostProcessor,所以容器启动的过程中,会为符合AOP规则的bean创建动态代理加入到容器中;

容器在启动的时候会在九处调用后置处理器,如下图,也是自己画的:
Spring AOP源码解读(@Aspect注解)
那么接下来直接上代码:
容器启动的时候会执行org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessBeforeInstantiation:

@Override
	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
		//获取当前bean是否可以创建AOP的缓存
		Object cacheKey = getCacheKey(beanClass, beanName);

		//当前是否为是 TargetSource对象,通过自定义targetSource对象可以获取对象,这里就不对此用法做出详解
		if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
			//判断当前bean是否被解析过
			if (this.advisedBeans.containsKey(cacheKey)) {
				return null;
			}
			//1、判断当前Bean是否A为OP的相关基础类Advice.class	Pointcut.class Advisor.class AopInfrastructureBean
			//2、判断当前bean是否为AspectJPointcutAdvisor :如果  <aop:aspect ref="beanName"> 就会生成此类
			//3、如何符合上述条件,则说明不需要进行AOP,加入到缓存中advisedBeans.put(cacheKey, Boolean.FALSE);
			//shouldSkip这个里面的逻辑还是比较多的:
			// a、它会获取xml配置的Advisor和原生接口的AOP的Advisor ,在第一次doCreateBean时会把获取
			//到的beanName缓存到BeanFactoryAdvisorRetrievalHelper.cachedAdvisorBeanNames缓存中,后面会接着使用
			// b、获取@Aspect中配置的Advisor,把得到的Advisor的beanName缓存BeanFactoryAspectJAdvisorsBuilder.aspectBeanNames,
			// 的到的对象缓存到Map<String, List<Advisor>> advisorsCache = new ConcurrentHashMap<>()
			//c、接着判断当前bean是否是AspectJPointcutAdvisor
			if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
				this.advisedBeans.put(cacheKey, Boolean.FALSE);
				return null;
			}
		}

		// Create proxy here if we have a custom TargetSource.
		// Suppresses unnecessary default instantiation of the target bean:
		// The TargetSource will handle target instances in a custom fashion.
		//如果是自定义的 TargetSource对象,则不进行后面doCreateBean的操作,直接进行AOP的操作
		TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
		if (targetSource != null) {
			if (StringUtils.hasLength(beanName)) {
				this.targetSourcedBeans.add(beanName);
			}
			Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
			Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		return null;
	}

接着执行org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization,也就是这一步创建了代理对象。

	@Override
	public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
		if (bean != null) {
			//获取当前Bean相关AOP使用的Key;
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			//因为循环依赖创建的AOP动态代理,则不在创建,并且直接移除
			if (this.earlyProxyReferences.remove(cacheKey) != bean) {
				//这个里面逻辑比较多,是AOP创建动态代理并且返回
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}

下面的代码时上面两个方法入口的具体细节方法,如果后期自己调试,可以根据我的注释进行理解:

	@Override
	protected boolean shouldSkip(Class<?> beanClass, String beanName) {
		// TODO: Consider optimization by caching the list of the aspect names
		//找到所有候选的Advisors(通知  前置通知、后置通知等..)InstantiationModelAwarePointcutAdvisorImpl
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
		// 判断这个类的原因在于:
		// AspectJPointcutAdvisor 是xml <aop:advisor 解析的对象
		// 如果  <aop:aspect ref="beanName"> 是当前beanName 就说明当前bean是切面类  那就跳过。
		for (Advisor advisor : candidateAdvisors) {
			if (advisor instanceof AspectJPointcutAdvisor &&
					((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
				return true;
			}
		}
		return super.shouldSkip(beanClass, beanName);
	}
public List<Advisor> buildAspectJAdvisors() {
		//获取缓存中切面
		List<String> aspectNames = this.aspectBeanNames;
		//如果切面不为null,则所用已经解析过容器中的切面,不用在进行解析
		if (aspectNames == null) {
			//加锁
			synchronized (this) {
				//再进行一次判断
				aspectNames = this.aspectBeanNames;
				if (aspectNames == null) {
					List<Advisor> advisors = new ArrayList<>();
					aspectNames = new ArrayList<>();
					//获取根据类型获取容器中所有的BeanName, 包括Bean定义和一级缓存中的;传的是object类型,说明获取所有的beanName
					String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
							this.beanFactory, Object.class, true, false);
					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.
						//通过beanName获取class对象
						Class<?> beanType = this.beanFactory.getType(beanName, false);
						if (beanType == null) {
							continue;
						}
						//判断当前class是否有@Aspect 是否为切面  (其实也判断了属性中是否有ajc$开开通的)
						if (this.advisorFactory.isAspect(beanType)) {
							aspectNames.add(beanName);
							//把beanName和class对象构建成一个AspectMetadata对象
							AspectMetadata amd = new AspectMetadata(beanType, beanName);
							/**
							 * AspectJ的singleton、perthis、pertarget、pertypewithin实例化模型(目前不支持percflow、percflowbelow)  参见枚举类PerClauseKind
							 * // 他将为每个被切入点表达式匹配上的代理对象,都创建一个新的切面实例(此处允许HelloService是接口)
							 * @Aspect("perthis(this(com.fsx.HelloService))")
							 * @Aspect("pertarget(切入点表达式)")指定切入点表达式; 此处要求HelloService不能是接口
							 *
							 *  另外需要注意一点:若在Spring内要使用perthis和pertarget,请把切面的Scope定义为:prototype
							 *
							 */
							if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
								//根据容器对象和beanName构建切面工厂对象
								MetadataAwareAspectInstanceFactory factory =
										new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
								//advisorFactory=  new ReflectiveAspectJAdvisorFactory(beanFactory)  其在初始化AnnotationAwareAspectJAutoProxyCreator中赋值的
								//根据切面  获取所有的Advisor对象InstantiationModelAwarePointcutAdvisorImpl
								List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
								if (this.beanFactory.isSingleton(beanName)) {
									//加入到缓存中,key为beanName,value为解析出来的Advisor对象集合
									this.advisorsCache.put(beanName, classAdvisors);
								}
								else {
									this.aspectFactoryCache.put(beanName, factory);
								}
								advisors.addAll(classAdvisors);
							}
							else {
								// Per target or per this.
								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.addAll(this.advisorFactory.getAdvisors(factory));
							}
						}
					}
					this.aspectBeanNames = aspectNames;
					//返回容器中所有的Advisor对象
					return advisors;
				}
			}
		}

		if (aspectNames.isEmpty()) {
			return Collections.emptyList();
		}
		List<Advisor> advisors = new ArrayList<>();
		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;
	}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}

		// Create proxy if we have advice.
		//找根据当前的bean,找到符合的advisor
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		if (specificInterceptors != DO_NOT_PROXY) {
			//在缓存中,标记为已经处理
			this.advisedBeans.put(cacheKey, Boolean.TRUE);
			//创建我们真正的代理对象:传参为 当前beanClass beanName  符合的Advisor  当前bean
			Object proxy = createProxy(
					bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}
@Override
	@Nullable
	protected Object[] getAdvicesAndAdvisorsForBean(
			Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {

		//根据bean找到合适的daviosr
		List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
		if (advisors.isEmpty()) {
			return DO_NOT_PROXY;
		}
		return advisors.toArray();
	}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
		//找到所有候选的Advisor,这一步会走缓存,因为在第一次创建bean的时候,在实例化之前已经把容器中所有的Advisor进行了缓存
		//包括:XML中配置的,传统的实现了Advisor接口的和@AspectJ注解的
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
		//利用所有的的advisor和当前的bean相匹配,找到符合条件的Advisor,比如注解的会利用切点是否匹配到当前Bean中的任意method
		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
		//这一步主要是加入ExposeInvocationInterceptor.DefaultPointcutAdviso匿名内部类,其作用就是第一个在执行目标方法时,
		//以责任链模式执行通知和切点时放在第一位执行,调用后面的真正通知方法
		extendAdvisors(eligibleAdvisors);
		//对Advisor进行排序:这个排序在5.2.7之后只能进行切面的排序了@Order这种注解排序,之前版本的spring是利用这个排序前面的排序反过来
		//调用这一步之前已经排好序了,是解析切面创建Advisor对象时排序的Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class
		if (!eligibleAdvisors.isEmpty()) {
			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
		}
		return eligibleAdvisors;
	}
	protected List<Advisor> findAdvisorsThatCanApply(
			List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {

		//把当前beanName放在ThreadLocal中
		ProxyCreationContext.setCurrentProxiedBeanName(beanName);
		try {
			//从候选的Advisor中获取到beanName匹配的Advisor;逻辑比较多的
			return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
		}
		finally {
			//把当前beanName放在ThreadLocal中
			ProxyCreationContext.setCurrentProxiedBeanName(null);
		}
	}
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
		if (candidateAdvisors.isEmpty()) {
			return candidateAdvisors;
		}
		//定义一个装载载返回结果的list
		List<Advisor> eligibleAdvisors = new ArrayList<>();
		//循环候选的Advisor
		for (Advisor candidate : candidateAdvisors) {
			//IntroductionAdvisor只能应用于类级别的拦截,判断Advisor是否实现此接口;如果是则进行类级别的匹配ClassFilter getClassFilter()
			if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
				//把匹配到当前bean的IntroductionAdvisor类型的Advisor加入到结果集中
				eligibleAdvisors.add(candidate);
			}
		}
		//如果候选的Advisor中存在IntroductionAdvisor,则为true,否则为false
		boolean hasIntroductions = !eligibleAdvisors.isEmpty();
		for (Advisor candidate : candidateAdvisors) {
			if (candidate instanceof IntroductionAdvisor) {
				// already processed
				//上面已经处理过了,就不需要处理了
				continue;
			}
			//判断当前候选的Advisor是否匹配当前的bean,如果匹配,则加入到结果集中,一般为方法级别的匹配
			if (canApply(candidate, clazz, hasIntroductions)) {
				//如果匹配上,则进行
				eligibleAdvisors.add(candidate);
			}
		}
		return eligibleAdvisors;
	}

public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
		//ClassFilter getClassFilter()再次判断是否是IntroductionAdvisor
		if (advisor instanceof IntroductionAdvisor) {
			return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
		}
		//判断是否为PointcutAdvisor,方法级别的匹配
		else if (advisor instanceof PointcutAdvisor) {
			//获取切点对象
			PointcutAdvisor pca = (PointcutAdvisor) advisor;
			//判断是否匹配,只要有一个方法匹配上就进行返回。兼容有AspectJ 切点表达式和实现内部AOP接口的方式的匹配
			return canApply(pca.getPointcut(), targetClass, hasIntroductions);
		}
		else {
			// It doesn't have a pointcut so we assume it applies.
			return true;
		}
	}
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
		Assert.notNull(pc, "Pointcut must not be null");
		//进行类级别的过滤,通过AspectJ
		if (!pc.getClassFilter().matches(targetClass)) {
			return false;
		}

		/**
		 * 进行方法级别的过滤
		 */
        //如果pc.getMethodMatcher() 返回了MethodMatcher.TRUE,则匹配所有方法
		MethodMatcher methodMatcher = pc.getMethodMatcher();
		if (methodMatcher == MethodMatcher.TRUE) {
			// No need to iterate the methods if we're matching any method anyway...
			return true;
		}

		//判断匹配器是否属于IntroductionAwareMethodMatcher,AspectJExpressionPointcut就是实现了此接口
		IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
		if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
			//转换成IntroductionAwareMethodMatcher类型
			introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
		}

		//定义一个装class对象的集合
		Set<Class<?>> classes = new LinkedHashSet<>();
		//判断是否为代理对象,如果不是则加入到集合中
		if (!Proxy.isProxyClass(targetClass)) {
			classes.add(ClassUtils.getUserClass(targetClass));
		}
		//获取到当前bean的所有实现接口的class对象转载到集合中
		classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));

		//循环当前bean及其实现接口的所有class对象;
		//为啥要获取接口中方法名称是否匹配呢,因为是兼容事物,事务的注解可以加在接口上
		for (Class<?> clazz : classes) {
			//获取class对象的所有方法对象
			Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
			//循环所有的方法对象
			for (Method method : methods) {
				//利用切点皮匹配器进行方法的匹配,如果命中一个方法,则直接进行返回true,传参为当前方法对象和当前class对象
				if (introductionAwareMethodMatcher != null ?
						//通过切点表达式进行匹配 AspectJ方式  AspectJExpressionPointcut
						introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
						//通过方法匹配器进行匹配 内置aop接口方式
						methodMatcher.matches(method, targetClass)) {
					//任意匹配,则直接返回,创建代理
					return true;
				}
			}
		}

		return false;
	}
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();
		/**
		 * 把一些AOP的属性值传给代理工厂,比如proxyTargetClass是否全部使用CGLB代理  exposeProxy是否把当前对象暴露到当前线程中
		 * this.proxyTargetClass = other.proxyTargetClass;
		 * 		this.optimize = other.optimize;
		 * 		this.exposeProxy = other.exposeProxy;
		 * 		this.frozen = other.frozen;
		 * 		this.opaque = other.opaque;
		 */
		proxyFactory.copyFrom(this);

		//如果没有强制使用CGLB代理
		if (!proxyFactory.isProxyTargetClass()) {
			//判断bean定义中有没有使用CGLB代理的属性,一般配置类上可以配置
			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}
			else {
				//如果配置类没有指定,则如果当前Bean 有接口则是JDK动态代理,反之则是CGLB动态代理
				evaluateProxyInterfaces(beanClass, proxyFactory);
			}
		}

		//把传入的Advisor转成数组,把所有的增强器都转成Advisor类型
		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		//把Advisor数组传给代理工厂
		proxyFactory.addAdvisors(advisors);
		//传入目标对象SingletonTargetSource
		proxyFactory.setTargetSource(targetSource);
		//空方法
		customizeProxyFactory(proxyFactory);

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

		//利用代理工厂创建代理对象;传参为类加载器对象,代理工厂已经具有了目标对象bean、 Advisor数组、使用JDK还是CGLB
		return proxyFactory.getProxy(getProxyClassLoader());
	}
	public Object getProxy(@Nullable ClassLoader classLoader) {
		// createAopProxy()来获取使用JDK代理JdkDynamicAopProxy 还是CGLB代理ObjenesisCglibAopProxy
		return createAopProxy().getProxy(classLoader);
	}

JDK动态代理

@Override
	public Object getProxy(@Nullable ClassLoader classLoader) {
		if (logger.isTraceEnabled()) {
			logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
		}
		//这个advised其实就是ProxyFactory,其属性中有一个存储目标类所有接口class对象的数组,值是在前面的决定使用jdk
		//动态代理设置上的
		Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
		findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
		//这和我们创建普通的jdk动态代理一样
		// Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
		//第一个参数为类加载器 、第二个参数为目标类的所有接口的class对象,第三个参数为实现InvocationHandler接口的对象,
		//也就是当前对象,它是实现了此方法;这样就完整返回了JDK动态代理对象
		return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
	}

CGLB代理

@Override
	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...
			//创建CGLB使用的Enhancer对象
			Enhancer enhancer = createEnhancer();
			if (classLoader != null) {
				enhancer.setClassLoader(classLoader);
				if (classLoader instanceof SmartClassLoader &&
						((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
					enhancer.setUseCache(false);
				}
			}
			//设置被代理的对象的class
			enhancer.setSuperclass(proxySuperClass);
			enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
			enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
			enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));

			//获取到callBack:   DynamicAdvisedInterceptor   DynamicUnadvisedExposedInterceptor
			//SerializableNoOp  StaticDispatcher  AdvisedDispatcher new EqualsInterceptor(this.advised),
			//				new HashCodeInterceptor(this.advised)

			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
			//这个比较重要,因为后面设置了多个callBack, 这一步判断使用哪一个callBack ,正常下有7个callBack ,最重要的还是
			//AOP的使用DynamicAdvisedInterceptor
			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);
		}
	}

先看一下执行CGLB代理的方法,其实实现方式和JDK的一样,都是责任链:

/**
		 *
		 * @param proxy 代理对象
		 * @param method 目标方法
		 * @param args 方法参数
		 * @param methodProxy
		 * @return
		 * @throws Throwable
		 */
		@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) {
					// 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);
				//这个advised是前面创建的ProxyFactry对象,可以拿到排好序的MethodInterceptor(这个是AOP自己的接口); 这个排序规则和spring-5之前的版本是不一样的
				//ExposeInvocationInterceptor
				//AspectJAroundAdvice
				//MethodBeforeAdviceInterceptor
				//AspectJAfterAdvice
				//AfterReturningAdviceInterceptor
				//AspectJAfterThrowingAdvice
				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.
				//如何没有Interceptor,则直接执行目标方法
				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...
					//递归chain顺序执行,责任链的形式,创建CGLB方法执行器:
					//传参: 动态代理对象、被代理的目标对象、目标方法、目标方法参数、目标对象的calss对象、MethodProxy
					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);
				}
			}
		}
@Override
		@Nullable
		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);
				}
			}
		}

下面的代码就是利用责任链执行通知方法和目标方法:

@Override
	@Nullable
	public Object proceed() throws Throwable {
		// We start with an index of -1 and increment early.
		//interceptorOrInterceptionAdvice从-1开始
		//当执行完所有的方法拦截器之后,最后一个执行目标方法;
		if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
			//执行目标方法methodProxy.invoke(target, objects);
			return invokeJoinpoint();
		}

		//分别按以下顺序递归调用拦截器 都实现了 MethodInterceptor接口
		// 			ExposeInvocationInterceptor
		//			AspectJAroundAdvice
		//				//MethodBeforeAdviceInterceptor
		//				//AspectJAfterAdvice
		//				//AfterReturningAdviceInterceptor
		//				//AspectJAfterThrowingAdvice
		Object interceptorOrInterceptionAdvice =
				this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
		if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
			// Evaluate dynamic method matcher here: static part will already have
			// been evaluated and found to match.
			InterceptorAndDynamicMethodMatcher dm =
					(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
			Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
			if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
				return dm.interceptor.invoke(this);
			}
			else {
				// Dynamic matching failed.
				// Skip this interceptor and invoke the next in the chain.
				return proceed();
			}
		}
		else {
			// It's an interceptor, so we just invoke it: The pointcut will have
			// been evaluated statically before this object was constructed.
			//调用MethodInterceptor拦截器的invoke方法,把当前对象ReflectiveMethodInvocation  this传入
			//因为是递归调用,每次执行invoke方法的参数都是第一步new CglibMethodInvocation对象(子类中调用父类的方法.则在父类中
			// 获取的this就是子类对象)
			/**
			 *  以ReflectiveAspectJAdvisorFactory中的Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class
			 *  顺序进行Advisor 的排序的,
			 *  每次都是递归调用当前的 proceed()方法,所以其属性currentInterceptorIndex每执行一次就会加一;每次按顺序获取
			 *  到不同的Advice,然后执行方法
			 *  以			ExposeInvocationInterceptor
			 *  			AspectJAroundAdvice
			 * 		//				//MethodBeforeAdviceInterceptor
			 * 		//				//AspectJAfterAdvice
			 * 		//				//AfterReturningAdviceInterceptor
			 * 		//				//AspectJAfterThrowingAdvice
			 * 	为例:
			 * 	 currentInterceptorIndex =0 先执行ExposeInvocationInterceptor : 把当前的CglibMethodInvocation暴露到threadLocal中,执行完成再清除
			 *
			 *	currentInterceptorIndex =1 AspectJAroundAdvice :先执行环绕通知的前置通知:会调用环绕通知中的方法执行pjp.proceed();这样又会递归到CglibMethodInvocation.proceed方法
			 *
			 * 	currentInterceptorIndex =2 MethodBeforeAdviceInterceptor :先执行前置通知;然后调用CglibMethodInvocation.proceed方法
			 *
			 * 	currentInterceptorIndex =3 AspectJAfterAdvice :先执行CglibMethodInvocation.proceed方法(这一步会递归到这里,下标递增),在finally里包含了执行后置通知的代码
			 *
			 *  currentInterceptorIndex =4 AfterReturningAdviceInterceptor :先执行CglibMethodInvocation.proceed方法(这一步会递归到这里,下标递增),然后执行返回通知方法
			 *
			 *  currentInterceptorIndex =5 AspectJAfterThrowingAdvice :先执行CglibMethodInvocation.proceed方法(这一步会递归到这里,下标递增),在catch里包含了执行异常通知的代码
			 *
			 *  currentInterceptorIndex =6 这时候满足了下标等于advice集合中元素的个数;执行invokeJoinpoint方法:methodProxy.invoke(this.target, this.arguments)
			 *  我们熟悉的执行目标对象方法
			 *
			 *  但currentInterceptorIndex =6 目标方法执行完毕,返回结果,那么返回到AspectJAfterThrowingAdvice,如果有异常执行异常通知的代码,执行完毕;
			 *  接着执行AfterReturningAdviceInterceptor执行返回通知方法,执行完毕;接着进入AspectJAfterAdvice执行
			 *
			 *  这样又会回到环绕通知的方法中pjp.proceed()执行完毕,环绕通知执行完毕
			 *
			 *  这样又因为currentInterceptorIndex =6是直接return的,所以 会进入到调用栈AspectJAfterThrowingAdvice接着执行:如果有异常测进入到catch中
			 *  接着进入finally包裹的MethodBeforeAdviceInterceptor后置通知方法,执行结束
			 *  进入AspectJAfterAdvice 执行finally里包含了执行后置通知的代码 执行结束
			 *
			 *  这个执行方案和之前方案的对比就是,如果前制通知没有执行成功则,后面的通知不会执行;之前的版本前置通知是放在调用链的最后一个,后置通知在finally,不管调用链是否执行成功
			 *  都会执行后置通知
			 *
			 */
			return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
		}
	}

JDK动态代理执行方法:没有注释,因为正在的逻辑就是上面的责任链那块代码。

@Override
	@Nullable
	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.
				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;

			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;
			}
			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);
			}
		}
	}
上一篇:SQL Server - 索引详细教程 (聚集索引,非聚集索引)


下一篇:Android安全问题 抢先接收广播 - 内因篇之广播发送流程