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⃣️执行反射调用。