ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

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

2021-05-22 16:01:20  阅读:232  来源: 互联网

标签:beanName return target Spring Object class 源码 Aspect method


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

结果为:在这里插入图片描述
从结果看,使用了责任链的方式对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注解的源码解析

先上自己画的流程图:
在这里插入图片描述
直接上代码:不做过多解释,因为代码上都有注释:

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

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

容器在启动的时候会在九处调用后置处理器,如下图,也是自己画的:
在这里插入图片描述
那么接下来直接上代码:
容器启动的时候会执行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);
			}
		}
	}

标签:beanName,return,target,Spring,Object,class,源码,Aspect,method
来源: https://blog.csdn.net/qq_38166592/article/details/117157143

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有