spring AopUtils分析

AopUtils是spring aop中很常用的一个工具类,提供了许多通用方法:

一、isJdkDynamicProxy

public static boolean isJdkDynamicProxy(@Nullable Object object) {
	return (object instanceof SpringProxy && Proxy.isProxyClass(object.getClass()));
}

1)、方法描述:
判断当前对象是否是由JDK动态代理产生的代理对象
2)、执行逻辑:
1⃣️ 首先判断对象是否实现SpringProxy接口(注:spring产生的代理对象都会实现SpringProxy接口,具体原理可以参见:具体原理研究
2⃣️ 继而判断当前对象是否是JDK动态代理产生的代理对象。
只有当两者都满足的时候,才会返回true,表示该对象是spring JDK动态代理方式产生的代理对象。
3)、实现原理:
JDK动态代理产生的代理对象1⃣️会继承Proxy类,2⃣️已经产生的代理对象将会保存在proxyClassCache中,使用此方种式进行判断。(注:JDK动态代理产生的代理类都会有$Proxy前缀,笔者认为这里还可以根据类的名称进行判断,不过既然JDK的Proxy类已经提供了对应的功能,我们也不必要再造轮子了。)

 public static boolean isProxyClass(Class<?> cl) {
      return Proxy.class.isAssignableFrom(cl) && proxyClassCache.containsValue(cl);
   }

二、isCglibProxy

public static boolean isCglibProxy(@Nullable Object object) {
	return (object instanceof SpringProxy && ClassUtils.isCglibProxy(object));
}

1)、方法描述:
判断当前对象是否是由CGLIB产生的代理对象
2)、执行逻辑:
1⃣️ 首先判断对象是否实现SpringProxy接口;
2⃣️ 继而使用ClassUtils.isCglibProxy方法判断当前对象是否是CGLIB产生的代理对象。
只有当两者都满足的时候,才会返回true,表示该对象是由CGLIB产生的代理对象。
3)、实现原理:
CGLIB产生的代理类名中会包含$$符号,使用此种方式进行判断,具体判断逻辑如下:

public static boolean isCglibProxy(Object object) {
	return isCglibProxyClass(object.getClass());
}

public static boolean isCglibProxyClass(@Nullable Class<?> clazz) {
	return (clazz != null && isCglibProxyClassName(clazz.getName()));
}
public static boolean isCglibProxyClassName(@Nullable String className) {
	return (className != null && className.contains(CGLIB_CLASS_SEPARATOR));
}

三、isAopProxy

public static boolean isAopProxy(@Nullable Object object) {
	return (object instanceof SpringProxy &&
			(Proxy.isProxyClass(object.getClass()) || ClassUtils.isCglibProxyClass(object.getClass())));
}

1)、方法描述:
判断当前对象是否是AOP代理对象
2)、执行逻辑:
1⃣️ 首先判断对象是否实现SpringProxy接口;
2⃣️ 继而使用如下代码判断当前对象是否是AOP代理对象。

(Proxy.isProxyClass(object.getClass()) || ClassUtils.isCglibProxyClass(object.getClass())

3)、实现原理:
代理对象无非两种,JDK动态代理产生的代理对象或者CGLIB产生的代理对象,这里进行了或运算,无论当前对象是JDK动态代理产生的代理对象,还是CGLIB产生的代理对象,只要满足其一,就代表当前对象是AOP代理对象。

四、isEqualsMethod

public static boolean isEqualsMethod(@Nullable Method method) {
	return ReflectionUtils.isEqualsMethod(method);
}

1)、方法功能:
判断当前方法是否是Equals方法。
… isHashCodeMethod、isToStringMethod也是如此,分别判断当前方法是否是HashCode、toString方法,在这里不再赘述。

五、canApply

//判断targetClass类是否匹配切点的切入条件,或者说判断pc切点能否应用在targetClass类上
public static boolean canApply(Pointcut pc, Class<?> targetClass) ;

具体实现如下所示:

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 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<Class<?>> classes = new LinkedHashSet<>();
		if (!Proxy.isProxyClass(targetClass)) {
			classes.add(ClassUtils.getUserClass(targetClass));
		}
		classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));

		//判断类中的方法是否匹配切点函数
		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;
	}

六、findAdvisorsThatCanApply

public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) 

1)、方法描述:
根据candidateAdvisors,挑选出可以应用在clazz类上的Advisor集合。

if (candidateAdvisors.isEmpty()) {
	return candidateAdvisors;
	}
	List<Advisor> eligibleAdvisors = new ArrayList<>();
	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)) {
			eligibleAdvisors.add(candidate);
		}
	}
	return eligibleAdvisors;

2)、实现原理:
通过上面的代码块,我们可以看到,该方法最终是通过调用canApply方法来判断对应的Advisor能否应用在目标clazz上。

七、invokeJoinpointUsingReflection

@Nullable
public static Object invokeJoinpointUsingReflection(@Nullable Object target, Method method, Object[] args)
		throws Throwable {
	ReflectionUtils.makeAccessible(method);
	return method.invoke(target, args);
	...	
}

1)、方法描述:
使用反射调用目标方法。
2)、执行过程:
1⃣️首先调用了ReflectionUtils.makeAccessible(method),相当于method.setAccsessible(true),避免了反射调用过程中的安全检查。
2⃣️执行反射调用。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring 源码分析是一个相对复杂和庞大的话题,无法在一次对话中详细讨论。不过,我可以给你提供一些关于 Spring 源码分析的一般指导和建议。 1. 了解 Spring 的核心模块:Spring 框架是模块化的,每个模块都有不同的功能和职责。在开始源码分析之前,你需要先了解 Spring 的核心模块,如 Spring Core、Spring MVC、Spring Data 等。 2. 阅读官方文档和源码注释:Spring 框架的官方文档和源码注释是你学习和理解源码的重要资源。官方文档提供了对 Spring 各个模块的详细说明,源码注释则解释了代码的作用和实现细节。 3. 调试和跟踪代码:在进行源码分析时,调试器是你的好帮手。通过设置断点、单步跟踪以及观察变量的值,你可以深入理解代码的执行流程和逻辑。 4. 理解设计模式和原理:Spring 框架采用了许多设计模式和原理来实现其功能。在分析源码时,你需要熟悉这些设计模式和原理,例如依赖注入、AOP、工厂模式等。 5. 参考开源社区和博客:Spring 框架是一个非常活跃的开源社区,许多开发者在博客和论坛上分享了他们的源码分析和理解。阅读这些文章可以帮助你更好地理解 Spring 框架的实现细节。 请记住,深入分析 Spring 源码需要耐心和时间投入,同时也需要有一定的 Java 和设计模式的基础。希望这些指导对你有所帮助!如果你有具体的问题或者需要更详细的信息,欢迎继续提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值