Spring的aop源码分析

        在之前的文章中我已经详细的说明了关于Spring的aop的使用,大家有兴趣的可以翻一下之前的文章【spring】Spring的aop的使用详解

        今天,我就带着大家一起来走进aop源码,看看其内部具体是如何实现的。

一、环境准备

1.1、引入依赖

 
        UTF-8
        UTF-8
        1.8
        1.8
        1.8
        5.1.6.RELEASE
        4.12
        1.7.35
        1.8.9
        1.2.27
    

    
        
            org.springframework
            spring-context
            ${spring.version}
        
        
            org.springframework
            spring-test
            ${spring.version}
        
        
            junit
            junit
            ${junit.version}
            test
        
        
            org.slf4j
            slf4j-log4j12
            ${slf4j.version}
        
        
            org.aspectj
            aspectjweaver
            ${aspectjweaver.version}
        
        
            com.alibaba
            fastjson
            ${json.version}
        
    

1.2、编写接口和实现类

package com.sxx.controller.service;

public interface UserService {

    void work();
}
package com.sxx.controller.service.impl;

import com.sxx.controller.service.UserService;

public class UserServiceImpl implements UserService {
    @Override
    public void work() {
        System.out.println("UserServiceImpl执行了");
    }
}

1.3、编写切面

package com.sxx.controller.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import java.util.Arrays;

@Component
@Aspect
public class UserServiceAspect {

    @Pointcut(value = "execution(* com.sxx.controller.service.impl.*.* (..))")
    public void pointCut() {
        System.out.println("@进入切点...");
    }

    //环绕通知(连接到切入点开始执行,下一步进入前置通知,在下一步才是执行操作方法)
    @Around(value = "pointCut()")
    public void around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("@Around进入环绕通知...");
        long startTime = System.currentTimeMillis();
//		调用了下一个拦截器,递归调用ReflectiveMethodInvocation#proceed
        joinPoint.proceed();  // ===>  debug into,环绕round的下一个链
        long endTime = System.currentTimeMillis();
        System.out.printf("@Around方法执行耗时>>>>>: %s%n", endTime - startTime);
    }

    //前置通知(进入环绕后执行,下一步执行方法)
    @Before(value = "pointCut()")
    public void before(JoinPoint joinPoint) {
        System.out.println("@Before进入前置通知:" + Arrays.toString(joinPoint.getArgs()));
    }

    //异常通知(出错时执行)
    @AfterThrowing(value = "pointCut()", throwing = "ex")
    public void afterThrowing(JoinPoint joinPoint, Throwable ex) {
        System.out.println("@AfterThrowing进入异常通知" + Arrays.toString(joinPoint.getArgs()));

    }

    //后置通知(返回之前执行)
    @After(value = "pointCut()")
    public void after() {
        System.out.println("@After进入后置通知...");
    }

    //最终通知(正常返回通知,最后执行,出现异常)
    @AfterReturning(value = "pointCut()")
    public void afterReturning() {
        System.out.println("@AfterReturning进入最终通知...End!");
    }
}

1.4、编写xml文件





        
        
        
        
        
        

1.5、编写测试类

package com.sxx.controller;

import com.sxx.controller.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class UserController {

    public static void main(String[] args) {

        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:/application.xml");

        UserService userService = (UserService) applicationContext.getBean("userService");

        System.out.println(userService.getClass().getName());

        userService.work();
    }

}

1.6、结果

com.sun.proxy.$Proxy16
@Around进入环绕通知...
@Before进入前置通知:[]
UserServiceImpl执行了
@Around方法执行耗时>>>>>: 0
@After进入后置通知...
@AfterReturning进入最终通知...End!

二、aop源码解析 

        通过上面的执行结果我们可以看出,在打印userService.getClass().getName()打印出来的是com.sun.proxy.$Proxy16,我们知道proxy是代理类,我们在getBean的时候获取的应该是UserServiceImpl对象,怎么会被代理了呢?Spring又是在哪一步对UserServiceImpl做了代理动作呢?或许我们可以从源码中了解一二。

先放张aop的流程图:

        Spring的aop源码分析_第1张图片

2.1、Spring Bean是什么时候被代理的

        我们知道Spring在初始化Bean的时候有自己的一套流程,aop在代理bean这一过程肯定是发生在Spring初始化,那么具体是在初始化哪一步呢?如果大家对Spring Bean的生命周期还不太清楚,可以看下我之前的文章:

【Spring】Spring中bean的生命周期

        我们知道,如果想要代理一个事物,首先这个事物应该是已经存在(我们应当是可以进行描述),只有这样我们才能知道被替代的事物有哪些功能和属性等信息,然后才能创建一个新的代理去代替他。所以,代理类的创建肯定是在被代理类的bean已经创建好的阶段发生的,而Spring创建好bean后最后一步调用的是BeanPostProcessor,因此我们可以猜测,Spring创建代理类的是在BeanPostProcessor中。

2.2、BeanPostProcessor中做了些什么

2.2.1、initializeBean

      创建代理的入口是在initializeBean中,具体的可以查看org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(),源码如下:

    protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged((PrivilegedAction) () -> {
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		} else {
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {

			//调用Bean的前置处理器
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
			// 1、调用初始化方法, 处理 bean 中定义的 init-method,
			// 2、如果 bean 实现了 InitializingBean 接口,调用 afterPropertiesSet() 方法
			invokeInitMethods(beanName, wrappedBean, mbd);
		} catch (Throwable ex) {
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}
		if (mbd == null || !mbd.isSynthetic()) {
			// 调用Bean的后置管理器!aop的入口
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	} 
  

通过源码我们可以知道,在initializeBean主要做了三件事:

  1. 调用bean实现的前置处理器;
  2. 调用bean的初始化方法,即init-method以及afterPropertiesSet方法;
  3. 调用bean实现的后置处理器。

我们重点关注bean的后置处理器,这个是Spring aop的入口。

2.2.2、applyBeanPostProcessorsAfterInitialization

	@Override
	public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
			throws BeansException {
		Object result = existingBean;
		//aop
		//此处getBeanPostProcessors()有8个内置后置处理器;
		// 生成代理会调用里面的 AnnotationAwareAspectJAutoProxyCreator
		for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
			//Aop调用AnnotationAwareAspectJAutoProxyCreator#postProcessAfterInitialization
			// 所以,最好在这个for里,下面这行打断点,加断点表达式:
            // aop入口
        AnnotationAwareAspectJAutoProxyCreator
			Object current = beanProcessor.postProcessAfterInitialization(result, beanName); 
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
	}

注意:只有需要创建代理类的bean才能进入到AbstractAutoProxyCreator#postProcessAfterInitialization方法中,因此需要debug很多次才能进入。

2.2.3、postProcessAfterInitialization

    //如果当前的bean适合被代理,则需要包装指定的bean
	@Override
	public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
		if (bean != null) {
			// 根据给定的bean的class和name构建一个key
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			if (!this.earlyProxyReferences.contains(cacheKey)) {

				// 如果当前的bean适合被代理,则需要包装指定的bean
				// aop:注意看这个bean,这还是UserServiceImpl本尊,那么进去以后,情况变了~
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}

        可以看到postProcessAfterInitialization方法首先会给当前需要包装的bean构造一个key,然后判断当前的bean是否已经创建好对应的代理类了,如果没有就调用wrapIfNecessary方法去创建,那么wrapIfNecessary方法里面又做了哪些东西呢?

2.2.4、wrapIfNecessary

	//目标:代理对象的创建就藏在这货里面!!!
	//1、判断当前bean是否已经生成过代理对象
	//2、拿到切面类中的所有增强方法(拦截器:环绕、前置、后置等)
	//3、生成代理对象
	protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		//
		// 判断是否为空    否在TargetSource缓存中存在
		if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}
		// advisedBeans缓存了不需要代理的bean(为false的),如果缓存中存在,则可以直接返回
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}
		//Infrastructure基础设施
		// 判断bean是否为Spring自带bean,如果是,不用进行代理的
		// shouldSkip()则用于判断当前bean是否应该被略过
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			// 对当前bean进行缓存
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}

		//AOP:   【关键点 1 】
		// 找到哪些aspect的execution能匹配上当前bean
		// 匹配上的话列出前后和置换的方法(拦截器:环绕、前置、后置等),并且!!排好顺序 ===>
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);  // ===> debug进
		//debug后,仔细看一下上面这个数组内的值,其实就是UserServiceImpl里的匹配上的方法信息!
		//如果有匹配上的方法,就生成代理对象【关键点!】
		if (specificInterceptors != DO_NOT_PROXY) {
			// 允许创建代理对象的,设置为false
			this.advisedBeans.put(cacheKey, Boolean.TRUE);

			// 【关键节点 2 】
			// 开始创建AOP代理!!!!!!!!!!
			Object proxy = createProxy(
					bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); // ===>
			// 缓存生成的代理bean的类型,并且返回生成的代理bean
			this.proxyTypes.put(cacheKey, proxy.getClass());
			//此处返回的代理和在Main函数中返回的是一样的
			//说明此处代理成功创建,debug看一下proxy对象信息,变了~真身被隐藏
			return proxy;
		}
		//如果拿到的增强方法为空,缓存起来(使用false标记不需要代理)
		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}

        从wrapIfNecessary源码我们知道,它是Spring创建代理对象的核心,里面除了对创建代理对象时做的一些检查和校验外,最主要的功能有三个:

  1. 判断当前bean是否已经生成过代理对象;
  2. 拿到切面类中的所有增强方法(拦截器:环绕、前置、后置等);
  3. 创建对应的代理对象。

        在这里我们要重点关注两个方面,一是Spring是如何找到bean对应的环绕方法,二是Spring创建aop代理对象的过程。

三、Spring找到bean对应的环绕方法

3.1、getAdvicesAndAdvisorsForBean

        从刚才的源码中我们可以看出,Spring找到bean对应的环绕方法主要过程是在getAdvicesAndAdvisorsForBean这个方法中的,我们可以继续进去看看这个方法具体做了哪些东西。

    @Override
	@Nullable
	protected Object[] getAdvicesAndAdvisorsForBean(Class beanClass, String beanName, @Nullable TargetSource targetSource) {
		//AOP: 遍历所有注解了 @Aspectj 的类里的方法,将满足当前bean拦截条件的,封装成Advisor
		List advisors = findEligibleAdvisors(beanClass, beanName);  // ===>
		if (advisors.isEmpty()) {
			return DO_NOT_PROXY;
		}
		return advisors.toArray(); // 最终以数组形式返回
	}

         从上面可以看出getAdvicesAndAdvisorsForBean里面几乎没有做其他操作,只是调用了findEligibleAdvisors方法,看来真正实现这个功能是它调用的findEligibleAdvisors方法,这个方法具体做了哪些东西,我们继续点进去看。

3.2、findEligibleAdvisors

    protected List findEligibleAdvisors(Class beanClass, String beanName) {
		// 这是所有的切面里的方法(before,around,after……)!
		List candidateAdvisors = findCandidateAdvisors();
		// ===>  这是Pointcut匹配符合当前bean的
		List eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);  // ===> 进去!

		if (!eligibleAdvisors.isEmpty()) {
			// 排序,将来按这个顺序执行责任链!!!
			eligibleAdvisors = sortAdvisors(eligibleAdvisors); 
		}   // 将来执行责任链的时候,就是按照这个顺序,一环环推进的
		return eligibleAdvisors;
	}

findEligibleAdvisors方法中我们大致可以推测这个方法中完成的以下几件事:

  1. 拿到所有切面的通知方法;
  2. 根据当前beanName去匹配当前bean的通知方法
  3. 对当前bean的通知方法进行排序,后续通知链执行的时候就是按照这个顺序执行的。

 那么这些功能又是怎么实现的呢?接下来我们一个个跟踪源码解析这些方法。

3.3、 findCandidateAdvisors

    protected List findCandidateAdvisors() {
		Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
		return this.advisorRetrievalHelper.findAdvisorBeans();
	}
findCandidateAdvisors本身没有做什么,内部主要是调用advisorRetrievalHelper.findAdvisorBeans()方法,具体内容我们跟进去看下

3.4、findAdvisorBeans

    public List findAdvisorBeans() {
		// Determine list of advisor bean names, if not cached already.
		String[] advisorNames = null;
		synchronized (this) {
			advisorNames = this.cachedAdvisorBeanNames;
			if (advisorNames == null) {
				// Do not initialize FactoryBeans here: We need to leave all regular beans
				// uninitialized to let the auto-proxy creator apply to them!
				advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
						this.beanFactory, Advisor.class, true, false);
				this.cachedAdvisorBeanNames = advisorNames;
			}
		}
		if (advisorNames.length == 0) {
			return new LinkedList<>();
		}

		List advisors = new LinkedList<>();
		for (String name : advisorNames) {
			if (isEligibleBean(name)) {
				if (this.beanFactory.isCurrentlyInCreation(name)) {
					if (logger.isDebugEnabled()) {
						logger.debug("Skipping currently created advisor '" + name + "'");
					}
				}
				else {
					try {
						advisors.add(this.beanFactory.getBean(name, Advisor.class));
					}
					catch (BeanCreationException ex) {
						Throwable rootCause = ex.getMostSpecificCause();
						if (rootCause instanceof BeanCurrentlyInCreationException) {
							BeanCreationException bce = (BeanCreationException) rootCause;
							String bceBeanName = bce.getBeanName();
							if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {
								if (logger.isDebugEnabled()) {
									logger.debug("Skipping advisor '" + name +
											"' with dependency on currently created bean: " + ex.getMessage());
								}
								// Ignore: indicates a reference back to the bean we're trying to advise.
								// We want to find advisors other than the currently created bean itself.
								continue;
							}
						}
						throw ex;
					}
				}
			}
		}
		return advisors;
	}

在这个方法里只做了一件事,就是把BeanFactoryUtils.beanNamesForTypeIncludingAncestors拿到所有有切面方法bean的name集合,然后通过this.beanFactory.getBean拿到当前所有bean的通知。

3.5、findAdvisorsThatCanApply

	    protected List findAdvisorsThatCanApply(
			List candidateAdvisors, Class beanClass, String beanName) {

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

        findAdvisorsThatCanApply主要作用是根据当前beanName去获取对应的通知,从源码中可以看出除了将当前beanName放到和清除ThreadLocal的动作外还有一个方法AopUtils.findAdvisorsThatCanApply,我们根据方法名字即可猜测挑选Bean的通知方法应该是在这里完成的,我们可以进去看下其源码。

3.6、findAdvisorsThatCanApply

    public static List findAdvisorsThatCanApply(List candidateAdvisors, Class clazz) {
		if (candidateAdvisors.isEmpty()) {
			return candidateAdvisors;
		}
		List eligibleAdvisors = new LinkedList<>();
		for (Advisor candidate : candidateAdvisors) {
			if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
				eligibleAdvisors.add(candidate);
			}
		}
		boolean hasIntroductions = !eligibleAdvisors.isEmpty();
		for (Advisor candidate : candidateAdvisors) {
			if (candidate instanceof IntroductionAdvisor) {
				// already processed
				continue;
			}
			if (canApply(candidate, clazz, hasIntroductions)) {   // ===>  aop 会进canApply 判断 切面表达式是否符合当前bean
				eligibleAdvisors.add(candidate);  // 如果满足条件,就添加到可用数组里去,最终返回去
			}
		}
		return eligibleAdvisors;
	}

ps:关于IntroductionAdvisor和PointcutAdvisor大家可以自行百度下,本章就不再讲解。

3.7、canApply

	    public static boolean canApply(Advisor advisor, Class targetClass, boolean hasIntroductions) {
		if (advisor instanceof IntroductionAdvisor) {
			return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
		}
		else if (advisor instanceof PointcutAdvisor) {
			PointcutAdvisor pca = (PointcutAdvisor) advisor;
			return canApply(pca.getPointcut(), targetClass, hasIntroductions);   // ===>  aop 进!
		}
		else {
			// It doesn't have a pointcut so we assume it applies.
			return true;
		}
	}

 aop的通知属于PointcutAdvisor,因此最终走的是canApply方法,那么这个方法具体怎么做的呢?

    public static boolean canApply(Pointcut pc, Class targetClass, boolean hasIntroductions) {
		Assert.notNull(pc, "Pointcut must not be null");
		if (!pc.getClassFilter().matches(targetClass)) {
			return false;
		}
		// 留心这个 MethodMatcher 里的:pointcutExpression , 发现了什么???
		MethodMatcher methodMatcher = pc.getMethodMatcher();
		if (methodMatcher == MethodMatcher.TRUE) {
			// No need to iterate the methods if we're matching any method anyway...
			return true;
		}

		IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
		if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
			introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
		}

		Set> classes = new LinkedHashSet<>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
		classes.add(targetClass);   // targetClass 就是我们的  SlaveImpl 这个bean
		for (Class clazz : classes) {
			Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);  // 遍历它所有的方法,跟aop切面表达式匹配!
			for (Method method : methods) {   // 注意这个method,是不是我们的work方法???
				if ((introductionAwareMethodMatcher != null &&
						introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
						methodMatcher.matches(method, targetClass)) {   // 方法名是否匹配,就在这里!
					return true;   // 表达式 匹配这个方法,就返回true
				}
			}
		}

		return false;
	}

至此,Spring根据beanName去匹配对应的通知方法的过程就结束了,下面就剩最重要一步,即Spring为aop创建代理对象的过程。 

四、aop创建代理对象的过程

4.1、createProxy

从之前的源码可知,aop创建代理类的过程注释藏在AbstractAutoProxyCreator#createProxy,我们可以dubug进去追一下这个方法的源码。

	protected Object createProxy(Class beanClass, @Nullable String beanName,
								 @Nullable Object[] specificInterceptors, TargetSource targetSource) {
		//为true,DefaultListableBeanFactory
		if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
			//标记一下,当前的bean具备创建代理的资格
			//其实就是在BD设置了属性setAttribute("originalTargetClass",bean的class)
			AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
		}
		//创建一个默认的代理工厂DefaultAopProxyFactory,注意:父类无参构造器
		ProxyFactory proxyFactory = new ProxyFactory();


		//proxyFactory通过复制配置进行初始化
		//this为AbstractAutoProxyCreator对象,说明AbstractAutoProxyCreator继承参数实际类型
		proxyFactory.copyFrom(this);  // 设置了一堆属性,不管他
		/**
		 * true
		 * 目标对象没有接口(只有实现类) – 使用CGLIB代理机制
		 * false
		 * 目标对象实现了接口 – 使用JDK代理机制(代理所有实现了的接口)
		 */

		//默认值为false,为true,使用CGLIB,
		if (!proxyFactory.isProxyTargetClass()) {
			//来判断@EnableAspectJAutoProxy注解或者XML的proxyTargetClass参数(true或者false)
			//也就是:用户有没有明确指定什么方式生成代理
			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			} else {
				//评估接口的合理性,一些内部回调接口,比如InitializingBean等不要,我们自己的加入proxyFactory
				evaluateProxyInterfaces(beanClass, proxyFactory);  // ===>
			}
		}
		// 把前面我们过滤出来的那些切面方法,转成Advisor数组,specificInterceptors还有印象吧??
		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		//加入到代理工厂
		proxyFactory.addAdvisors(advisors);
		//设置要代理的类(目标类)
		proxyFactory.setTargetSource(targetSource);
		//子类实现,定制代理
		customizeProxyFactory(proxyFactory);
		//是否还允许修改通知,缺省值为false
		proxyFactory.setFrozen(this.freezeProxy);
		//设置预过滤
		if (advisorsPreFiltered()) {
			proxyFactory.setPreFiltered(true);
		}

		//【关键点!】proxyFactory携带了aop里配置的各种切面方法等等,由它来创建代理
		return proxyFactory.getProxy(getProxyClassLoader());   // ===>  aop藏在这里!代理类诞生的地方
	}

可以看到,在这个方法里面,Spring主要做了以下几件事情:

  1. 判断当前对象是否具有创建代理类的资格,设置标志位,并进行相关必要性校验;
  2. 创建代理工厂,然后根据被代理对象信息设置一大堆属性,并且将被代理对象的通知集合赋值给新的代理类;
  3. 开始创建代理对象。

        在createProxy方法中,其他方法都是在进行创建代理对象的必要性校验和属性赋值,最重要的方法还是proxyFactory.getProxy(getProxyClassLoader())方法,接下来我们进入这个方法看看它具体做了些什么。

4.2、getProxy

	//通过类加载期获取代理【重点方法!】
	public Object getProxy(@Nullable ClassLoader classLoader) {
		//分别进入createAopProxy (获取aopProxy对象)和getProxy(代理实例的方法)
		return createAopProxy().getProxy(classLoader);  // ===>  先进 createAopProxy 方法, 再进 getProxy 方法
	}

        在getProxy方法中它实际调用了createAopProxygetProxy两个方法,这两个方法至关重要,我们一个拆分来看,先来看看createAopProxy里做了什么。

4.3、createAopProxy

    protected final synchronized AopProxy createAopProxy() {
		if (!this.active) {
			activate();
		}
		//进入createAopProxy,查看返回jdk还是cglib
		return getAopProxyFactory().createAopProxy(this);   // ===> 进!
	}
    //走jdk还是走Cglib?【关键方法】
	@Override
	public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
		// isOptimize:  是否对代理进行优化
		// isProxyTargetClass:  值为true,使用CGLIB代理,默认false
		/**
		 * hasNoUserSuppliedProxyInterfaces:
		 * 	   1:接口是不是满足,如果长度为0;也就是接口为空,返回false
		 *	   2:如果接口类型不是SpringProxy类型的,也返回flase
		 */
		if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
			Class targetClass = config.getTargetClass();
			if (targetClass == null) {
				throw new AopConfigException("TargetSource cannot determine target class: " +
						"Either an interface or a target is required for proxy creation.");
			}
			// 如果目标对象实现了接口,默认情况下会采用JDK动态代理,
			// 但也可以通过配置(proxy-target-class=true)强制使用CGLIB。
			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
				//jdk
				return new JdkDynamicAopProxy(config);
			}
			//cglib
			return new ObjenesisCglibAopProxy(config);
		} else {
			//jdk代理 , 走这里!
			// 注意,config里面藏着了我们上面筛出来的那些 advisor(即切面方法,并且它们已经排好了顺序),
			return new JdkDynamicAopProxy(config);  // 【找到了!】 走的jdk动态代理,
			// 这货其实就是动态代理里的那个InvocationHandler,往回走
		}
	}

        可以看到,在createAopProxy最终走到了createAopProxy(AdvisedSupport config)方法中,而这个方法则是根据被代理类是否实现接口以及是否设置了proxy-target-class属性去选择是使用jdk动态代理还是走Cglib动态代理。

        接下来我们再回到getProxy去看getProxy(classLoader)方法,这个方法有两个实现JdkDynamicAopProxyCglibAopProxy,具体调用哪个方法需要看createAopProxy具体返回的信息来决定。

4.4、getProxy

我们以jdk动态代理为例来看下源码:

	//获取最终的代理对象(由JDK生成;运行时织入)
	@Override
	public Object getProxy(@Nullable ClassLoader classLoader) {
		if (logger.isDebugEnabled()) {
			logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
		}
		//获取代理对象需要实现的接口(业务接口和内置接口),不管他
		Class[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
		//判断接口中是否重写了equals和hashCode方法,也不用搭理他
		findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);

		/**
		 * 【关键点】 jdk动态代理的诞生!Proxy是jdk的动态代理生成工具类
		 * 第一个参数是类加载器(目标类)
		 * 第二个参数是目标类实现的接口(含系统接口)(数组)
		 * 第三个是InvocationHandler,也就是这个JdkDynamicAopProxy自己,它实现了handler接口
		 *  而前面的步骤,把筛出来的 一堆排好序的 advisor ,给了这货
		 *  未来真正调用代理方法的时候,这货的invoke被触发,开始使用这些advisor当责任链列表,一环环被调用……
		 *  而这,就是aop的真相~  其实很简单!
		 */
		return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);  // 真身被隐藏,proxy被创建!
	}

五、总结

        至此,Spring创建aop代理对象的过程就算是跟完了,但是,我们在实际调用的时候代理对象是怎么执行的以及jdk动态代理还是走Cglib动态代理具体使用上有什么不一样的,我将放在后面的课程讲解。

你可能感兴趣的:(#,Spring源码,spring,java)