Spring源码分析番外篇一:AOP


序言
本文主要是对Spring源码分析三:AOP篇做一个补充,因AOP篇幅受限,一些比较具体实现逻辑不能一一罗列,故新增加AOP补充篇一继续分析Spring源码AOP的实现逻辑。

(一)AOP获取增强方法

在Spring源码分析三中已提到AnnotationAwareAspectJAutoProxyCreator->findCandidateAdvisors->buildAspectJAdvisors->getAdvisors,
getAdvisors方法是获取增强方法的具体实现,也是本文的重点。

1、getAdvisors获取增强方法(核心)

buildAspectJAdvisors该方法是委托于BeanFactoryAspectJAdvisorsBuilder类去实现,其方法核心点是this.advisorFactory.getAdvisors(factory);getAdvisors方法是委托于ReflectiveAspectJAdvisorFactory去实现,具体代码如下:
getAdvisors核心逻辑:

1)验证切面类是否符合Spring AOP基本要求;
2)解析切面类中的所有方法,并根据PointCut注解定义的方法去匹配其他增强器,从而生成六大增强器,每种增强器处理方式各不相同;

public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
    //获取被AspectJ标记的类
	Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
	//获取被AspectJ标记的beanName
	String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
	//验证被AspectJ标记的类是否符合Spring AOP的要求
	validate(aspectClass);
	//懒加载实例化
	MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
			new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
	List<Advisor> advisors = new ArrayList<>();
	//getAdvisorMethods是获取被AspectJ注解类中的方法,但是排除掉PointCut注解外的方法
	for (Method method : getAdvisorMethods(aspectClass)) {
		Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
		if (advisor != null) {
			advisors.add(advisor);
		}
	}
	//判断是否有增强方法和是否配置有懒加载机制,如果都满足则在首位增加同步实例器
	if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
		Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
		advisors.add(0, instantiationAdvisor);
	}
	//获取被DeclareParents注解的增强字段,基于该注解的字段生成增强方法
	for (Field field : aspectClass.getDeclaredFields()) {
		Advisor advisor = getDeclareParentsAdvisor(field);
		if (advisor != null) {
			advisors.add(advisor);
		}
	}
	return advisors;
}

validate方法主要是验证被AspectJ标记的类,是否符合AOP的基本验证,包括Aspect注解、SpringAOP不支持的PerClauseKind.PERCFLOW和PerClauseKind.PERCFLOWBELOW等,代码如下:

public void validate(Class<?> aspectClass) throws AopConfigException {
    //验证aspectClass的父类是否有Aspect注解和抽象类修饰符
    if (aspectClass.getSuperclass().getAnnotation(Aspect.class) != null &&
            !Modifier.isAbstract(aspectClass.getSuperclass().getModifiers())) {
        throw new AopConfigException("[" + aspectClass.getName() + "] cannot extend concrete aspect [" +
                aspectClass.getSuperclass().getName() + "]");
    }
    AjType<?> ajType = AjTypeSystem.getAjType(aspectClass);
    //验证是否为Aspect注解
    if (!ajType.isAspect()) {
        throw new NotAnAtAspectException(aspectClass);
    }
    //验证aspectClass是否为PerClauseKind.PERCFLOW,不支持的类型
    if (ajType.getPerClause().getKind() == PerClauseKind.PERCFLOW) {
        throw new AopConfigException(aspectClass.getName() + " uses percflow instantiation model: " +
                "This is not supported in Spring AOP.");
    }
    //验证aspectClass是否为PerClauseKind.PERCFLOWBELOW,不支持的类型
    if (ajType.getPerClause().getKind() == PerClauseKind.PERCFLOWBELOW) {
        throw new AopConfigException(aspectClass.getName() + " uses percflowbelow instantiation model: " +
                "This is not supported in Spring AOP.");
    }
}

利用反射来获取切面类中的方法,但是又排除被PointCut注解的方法

private List<Method> getAdvisorMethods(Class<?> aspectClass) {
      final List<Method> methods = new ArrayList<>();
      ReflectionUtils.doWithMethods(aspectClass, method -> {
          //获取该切面类中的所有方法,除去有Pointcut注解的方法
          if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
              methods.add(method);
          }
      }, ReflectionUtils.USER_DECLARED_METHODS);
      if (methods.size() > 1) {
          methods.sort(METHOD_COMPARATOR);
      }
      return methods;
  }

先获取切点方法,然后根据切点信息去生成增强方法

public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
  			int declarationOrderInAspect, String aspectName) {
  	//同理上述被验证过validate的一样
      validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
      //获取切点方法,该切点就是PointCut中定义的方法与切面中的其他方法匹配如before、after、Around、AfterReturning、AfterThrowing注解等
      AspectJExpressionPointcut expressionPointcut = getPointcut(
              candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
      if (expressionPointcut == null) {
          return null;
      }
      //根据切点方法去生成增强方法
      return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
              this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
  }

2、canApply方法:匹配实际bean业务的增强器

封装增强器匹配方法,使用重载方法对不同业务场景调用

public static boolean canApply(Advisor advisor, Class<?> targetClass) {
	return canApply(advisor, targetClass, false);
}

封装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);
	}else {
		//没有匹配到业务,直接通过
		return true;
	}
}

canApply该重载方法主要是对引介增强的方法类型处理,包括强制转化匹配器,匹配切入点等

public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
    Assert.notNull(pc, "Pointcut must not be null");
    //获取ClassFilter即过滤器限制切入点或与给定目标类集的匹配并通过需要代理的类的类名来匹配
    if (!pc.getClassFilter().matches(targetClass)) {
        return false;
    }
    //获取切点的MethodMatcher方法匹配器
    MethodMatcher methodMatcher = pc.getMethodMatcher();
    if (methodMatcher == MethodMatcher.TRUE) {
        return true;//代表已经匹配到
    }
    //如果是引介增强类型的方法匹配器则转化为引介增强的
    IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
    if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
        introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
    }
    //将需要代理的类相关的接口转化为set集合的,跟这个类所有有关的接口都存储在classes中
    Set<Class<?>> classes = new LinkedHashSet<>();
    if (!Proxy.isProxyClass(targetClass)) {
        classes.add(ClassUtils.getUserClass(targetClass));
    }
    classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
    //遍历所有的class类的所有的方法,并去匹配对应的方法看是否存在对应的切点方法
    for (Class<?> clazz : classes) {
        Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
        for (Method method : methods) {
            if (introductionAwareMethodMatcher != null ?
                    introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
                    methodMatcher.matches(method, targetClass)) {
                return true;
            }
        }
    }
    return false;
}

(二)创建代理相关点

1、AOP封装Advisor:buildAdvisors方法

AbstractAutoProxyCreator类中负责封装Advisor,buildAdvisors方法是将容器中的拦截器和切面得到增强方法合并,对合并结果进行封装为Advisor,代码如下:

 protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
	//解析容器中注册的所有拦截器Interceptor
	Advisor[] commonInterceptors = resolveInterceptorNames();
	//存储合并的拦截器结果集
	List<Object> allInterceptors = new ArrayList<>();
	if (specificInterceptors != null) {
		allInterceptors.addAll(Arrays.asList(specificInterceptors));//加入拦截器
		if (commonInterceptors.length > 0) {
		    //加入容器中获取的拦截器
			if (this.applyCommonInterceptorsFirst) {
				allInterceptors.addAll(0, Arrays.asList(commonInterceptors));//首位添加
			}else {
				allInterceptors.addAll(Arrays.asList(commonInterceptors));//末尾添加
			}
		}
	}
	if (logger.isTraceEnabled()) {
		int nrOfCommonInterceptors = commonInterceptors.length;
		int nrOfSpecificInterceptors = (specificInterceptors != null ? specificInterceptors.length : 0);
		logger.trace("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors +
				" common interceptors and " + nrOfSpecificInterceptors + " specific interceptors");
	}
	//拦截器封装为Advisor
	Advisor[] advisors = new Advisor[allInterceptors.size()];
	for (int i = 0; i < allInterceptors.size(); i++) {
		advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
	}
	return advisors;
}

DefaultAdvisorAdapterRegistry类中负责将拦截器封装为Advisor,仅支持Advisor和Advice两种封装类型,伴随着MethodInterceptor类型和DefaultPointcutAdvisor类型的封装,代码如下:

public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
       //被封装对象本身就是Advisor,无须其他操作,直接转化返回
	if (adviceObject instanceof Advisor) {
		return (Advisor) adviceObject;
	}
	//封装对象必须为Advice或Advisor,否则抛出异常
	if (!(adviceObject instanceof Advice)) {
		throw new UnknownAdviceTypeException(adviceObject);
	}
	Advice advice = (Advice) adviceObject;
	if (advice instanceof MethodInterceptor) {
		//如果封装对象为MethodInterceptor类型,则使用DefaultPointcutAdvisor封装
		return new DefaultPointcutAdvisor(advice);
	}
	for (AdvisorAdapter adapter : this.adapters) {
		//如果AdvisorAdapter存在适配器,则判断是否需要使用默认的DefaultPointcutAdvisor进行封装
		if (adapter.supportsAdvice(advice)) {
			return new DefaultPointcutAdvisor(advice);
		}
	}
	throw new UnknownAdviceTypeException(advice);
}

2、JdkDynamicAopProxy代理下invoke方法

JdkDynamicAopProxy代理实现了InvocationHandler接口并重写了增强方法invoke,主要作用是否符合代理对象处理、拦截器链的处理以及切点方法的执行等。

@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)) {
			//代理类不实现equals方法,直接使用JdkDynamicAopProxy本身提供的equals方法进行对比
			return equals(args[0]);
		}else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
			//代理类不实现hashCode方法,直接使用JdkDynamicAopProxy本身提供的hashCode方法进行对比
			return hashCode();
		}else if (method.getDeclaringClass() == DecoratingProxy.class) {
			//该method方法的类型为DecoratingProxy时返回增强后的对象
			return AopProxyUtils.ultimateTargetClass(this.advised);
		}else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
				method.getDeclaringClass().isAssignableFrom(Advised.class)) {
			//调用该方法的class类型或接口和.class.isAssignableFrom(Advised.class)相同,则直接调用
			return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
		}
		Object retVal;
		//目标对象是否内部自我调用无法进行切面中的方法增强时的配置
		if (this.advised.exposeProxy) {
			//将代理对象赋值给辅助变量
			oldProxy = AopContext.setCurrentProxy(proxy);
			setProxyContext = true;
		}
		//获取目标对象
		target = targetSource.getTarget();
		Class<?> targetClass = (target != null ? target.getClass() : null);

		//获取当前方法的拦截器链
		List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

		//拦截器链无其他方法,则直接调用切点方法
		if (chain.isEmpty()) {
			//利用反射直接执行切点方法
			retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
		}else {
			//存在拦截器链时,将拦截器链封装到ReflectiveMethodInvocation中,便于proceed方法执行
			MethodInvocation invocation =
					new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
			//执行拦截器链
			retVal = invocation.proceed();
		}
		//获得返回结果类型
		Class<?> returnType = method.getReturnType();
		if (retVal != null && retVal == target &&
				returnType != Object.class && returnType.isInstance(proxy) &&
				!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
			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()) {
			//成功即释放
			targetSource.releaseTarget(target);
		}
		if (setProxyContext) {
			//失败则还原
			AopContext.setCurrentProxy(oldProxy);
		}
	}
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

进击的猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值