前言
Spring AOP
框架的代码结构组织得不可为不好,良好的面向对象的编程思想,其中很有一部分得益于它对代码的结构的把控。良好的封装、分层、隔离。而在其中起到重要作用的,便是本文要盘点的一些工具类。
Spring框架的工具类,其实它是分为内部工具类
和外部工具类
的。如果是外部工具类,那是可以给调用者使用的,如果是内部工具类,那它一般都是在Spring的流程内部使用。
Spring AOP工具类盘点
对此我们先构造这么一个环境:
代码语言:javascript复制public interface HelloService {
Object hello();
}
public class HelloServiceImpl implements HelloService {
@Override
public Object hello() {
System.out.println("this is my method~~");
return "service hello";
}
// 准备一个私有方法,测试用
private void privateMethod() {
System.out.println("privateMethod");
}
}
代码语言:javascript复制 private static HelloService getProxy(Object targetObj){
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(targetObj);
proxyFactory.addAdvice((MethodBeforeAdvice) (method, args1, target) -> {
System.out.println("方法之前执行了~~~");
});
HelloService helloService = (HelloService) proxyFactory.getProxy();
helloService.hello();
System.out.println(helloService.getClass().getName()); //com.fsx.service.HelloServiceImpl$$EnhancerBySpringCGLIB$$9b28670f
return helloService;
}
AopUtils
该工具类是Spring非常重要的一个工具类。显然它是一个外部工具类,我们平时若想要对AOP做一些判断、处理,也是可议使用此工具类的。
下面我们参照一些Demo,来做演示:
代码语言:javascript复制 public static void main(String[] args) {
HelloService helloService = getProxy(new HelloServiceImpl());
//===============演示AopUtils==================
// AopUtils.isAopProxy:是否是代理对象
System.out.println(AopUtils.isAopProxy(helloService)); // true
System.out.println(AopUtils.isJdkDynamicProxy(helloService)); // false
System.out.println(AopUtils.isCglibProxy(helloService)); // true
// 拿到目标对象
System.out.println(AopUtils.getTargetClass(helloService)); //class com.fsx.service.HelloServiceImpl
// selectInvocableMethod:方法@since 4.3 底层依赖于方法MethodIntrospector.selectInvocableMethod
// 只是在他技术上做了一个判断: 必须是被代理的方法才行(targetType是SpringProxy的子类,且是private这种方法,且不是static的就不行)
// Spring MVC的detectHandlerMethods对此方法有大量调用~~~~~
Method method = ClassUtils.getMethod(HelloServiceImpl.class, "hello");
System.out.println(AopUtils.selectInvocableMethod(method, HelloServiceImpl.class)); //public java.lang.Object com.fsx.service.HelloServiceImpl.hello()
// 是否是equals方法
// isToStringMethod、isHashCodeMethod、isFinalizeMethod 都是类似的
System.out.println(AopUtils.isEqualsMethod(method)); //false
// 它是对ClassUtils.getMostSpecificMethod,增加了对代理对象的特殊处理。。。
System.out.println(AopUtils.getMostSpecificMethod(method,HelloService.class));
}
接下来的几个方法都是关于Pointcut、Advisor
的,看源码分析会更好:
public abstract class AopUtils {
...
// 判断一个切入点能否匹配一个指定的类型 显然默认是不支持引介匹配
public static boolean canApply(Pointcut pc, Class<?> targetClass) {
return canApply(pc, targetClass, false);
}
//判断一个切入点能否匹配一个指定的类型,是否支持引介匹配;
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();
// 如果是恒等式true,那就毫无疑问全匹配楼
if (methodMatcher == MethodMatcher.TRUE) {
return true;
}
//IntroductionAwareMethodMatcher 是MethodMatcher的子类 增加了匹配方法:
// boolean matches(Method method, @Nullable Class<?> targetClass, boolean hasIntroductions);
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;
}
//判断一个建议(advisor)能否匹配一个指定的类型
public static boolean canApply(Advisor advisor, Class<?> targetClass) {
return canApply(advisor, targetClass, false);
}
// 同上,是否包含引介匹配
// 这个原理很简单,判断是否是IntroductionAdvisor还是PointcutAdvisor,然后做对应判断即可
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 {
// It doesn't have a pointcut so we assume it applies.
// 默认情况都是匹配的
return true;
}
}
//在给定的一组建议(advisor)中,返回能够匹配指定类型的建议者列表
// 这个方法很总要:在自动代理创建器AbstractAdvisorAutoProxyCreator中,都是这样筛选的能够匹配上此类型的Advisor们~~~
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new LinkedList<>();
// 这里遍历了candidateAdvisors两次 注意这个技巧
// 第一次遍历:找出所有的IntroductionAdvisor 类型的,并且canApply的Advisor们
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
// hasIntroductions:如果上面不为空,这里就是true 然后继续便利 吧canApply的找出来
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;
}
//通过反射,执行一个目标方法;这个方法其实就是method.invoke方法的更完善的方法,指在target对象上,使用args参数列表执行method
@Nullable
public static Object invokeJoinpointUsingReflection(@Nullable Object target, Method method, Object[] args)
throws Throwable {
try {
ReflectionUtils.makeAccessible(method);
return method.invoke(target, args);
} catch (InvocationTargetException ex) {
throw ex.getTargetException();
} catch (IllegalArgumentException ex) {
throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" method "] on target [" target "]", ex);
} catch (IllegalAccessException ex) {
throw new AopInvocationException("Could not access method [" method "]", ex);
}
}
}
AopConfigUtils
从名字可以看出,这个是关于AOP配置的工具类。因为配置AOP的方式有多种(比如xml、注解等),此工具类就是针对不同配置,提供不同的工具方法的。
它的好处是不管什么配置,最终走底层逻辑都让归一了~~~~
代码语言:javascript复制public abstract class AopConfigUtils {
// 这是注册自动代理创建器,默认的BeanName(若想覆盖,需要使用这个BeanName)
public static final String AUTO_PROXY_CREATOR_BEAN_NAME = "org.springframework.aop.config.internalAutoProxyCreator";
// 按照升级顺序 存储自动代理创建器(注意这里是升级的顺序 一个比一个强的)
private static final List<Class<?>> APC_PRIORITY_LIST = new ArrayList<>();
static {
APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
}
// 这两个:注册的是`InfrastructureAdvisorAutoProxyCreator`
// 调用处为:AutoProxyRegistrar#registerBeanDefinitions(它是一个ImportBeanDefinitionRegistrar实现类)
// 而AutoProxyRegistrar使用处为CachingConfigurationSelector,和`@EnableCaching`注解有关
// 其次就是AopNamespaceUtils有点用,这个下面再分析
@Nullable
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry,
@Nullable Object source) {
return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}
@Nullable
public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAspectJAutoProxyCreatorIfNecessary(registry, null);
}
// 下面这两个是注入:AspectJAwareAdvisorAutoProxyCreator
// 目前没有地方默认调用~~~~和Aop的xml配置方案有关的
@Nullable
public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAspectJAutoProxyCreatorIfNecessary(registry, null);
}
@Nullable
public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry,
@Nullable Object source) {
return registerOrEscalateApcAsRequired(AspectJAwareAdvisorAutoProxyCreator.class, registry, source);
}
// 这个就是最常用的,注入的是:AnnotationAwareAspectJAutoProxyCreator 注解驱动的自动代理创建器
// `@EnableAspectJAutoProxy`注入进来的就是它了
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry,
@Nullable Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
// 这两个方法,很显然,就是处理注解的两个属性值
// proxyTargetClass:true表示强制使用CGLIB的动态代理
// exposeProxy:true暴露当前代理对象到线程上绑定
// 最终都会放到自动代理创建器得BeanDefinition 里面去~~~创建代理的时候会用到此属性值
public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
}
}
public static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) {
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);
}
}
//========上面的注册自动代理创建器IfNecessary之类的方法,最终都是调用了这里========
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry,
@Nullable Object source) {
// 这里相当于,如果你自己定义了一个名称为这个的自动代理创建器,那也是ok的(需要注意的是使用工厂方法@Bean的方式定义,这里是会报错的)
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
// 若使用@Bean的方法定义,这里apcDefinition.getBeanClassName()就是null,导致后面的findPriorityForClass(apcDefinition.getBeanClassName())就会报错~~~~~~~ 需要特别的注意哦~~~~~
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}
// 绝大部分情况下都会走这里,new一个Bean定义信息出来,然后order属性值为HIGHEST_PRECEDENCE
// role是:ROLE_INFRASTRUCTURE属于Spring框架自己使用的Bean
// BeanName为:AUTO_PROXY_CREATOR_BEAN_NAME
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
...findPriorityForClass的逻辑省略
}
备注:请尽量不要自定义
自动代理创建器
,也不要轻易使用低级别的创建器,若你对原理不是非常懂的话,慎重
AopNamespaceUtils
这个从名字可以看出,是处理Spring AOP命名空间的工具类。比如
代码语言:javascript复制xmlns:aop="http://www.springframework.org/schema/aop
处理这种xml里面的
代码语言:javascript复制<aop:config />
<aop:advice />
等这种。当然还有对proxy-target-class
和expose-proxy
的处理。因为接下来的重点都不在xml里,因此此处略过(最终它调用都是AopConfigUtils#XXXIfNecessary
的方法,去注册不同的自动代理创建器的)
AopProxyUtils
我理解成它是对org.springframework.aop.support.AopUtils
的一个补充。
public static void main(String[] args) {
HelloService helloService = getProxy(new HelloServiceImpl());
//===============演示AopUtils==================
// 注意:此处的入参必须是一个Advised:也就是被代理过的对象,否则返回null
// 里面的TargetSource必须是SingletonTargetSource才会有所返回
//@since 4.3.8
System.out.println(AopProxyUtils.getSingletonTarget(helloService)); //com.fsx.service.HelloServiceImpl@17d677df
// 获取一个代理对象的最终对象类型
System.out.println(AopProxyUtils.ultimateTargetClass(helloService)); //class com.fsx.service.HelloServiceImpl
}
接下俩的方法,才是这个工具类真正厉害的方法:
代码语言:javascript复制public abstract class AopProxyUtils {
...
//很牛逼的方法来了,判断一个advised真正需要代理的目标接口列表
// 这个方法在getProxy()上都有应用,非常的重要。核心实现事下面的这个私有方法
public static Class<?>[] completeProxiedInterfaces(AdvisedSupport advised) {
return completeProxiedInterfaces(advised, false);
}
// 很显然发现,最终代理出来的对象,除了实现了自己的接口外,还实现了额外的接口,如:
// SpringProxy、Advised、DecoratingProxy等三个接口(备注:CGLIB代理未实现DecoratingProxy接口)
static Class<?>[] completeProxiedInterfaces(AdvisedSupport advised, boolean decoratingProxy) {
Class<?>[] specifiedInterfaces = advised.getProxiedInterfaces();
if (specifiedInterfaces.length == 0) {
// No user-specified interfaces: check whether target class is an interface.
Class<?> targetClass = advised.getTargetClass();
if (targetClass != null) {
if (targetClass.isInterface()) {
advised.setInterfaces(targetClass);
}
else if (Proxy.isProxyClass(targetClass)) {
advised.setInterfaces(targetClass.getInterfaces());
}
specifiedInterfaces = advised.getProxiedInterfaces();
}
}
boolean addSpringProxy = !advised.isInterfaceProxied(SpringProxy.class);
boolean addAdvised = !advised.isOpaque() && !advised.isInterfaceProxied(Advised.class);
boolean addDecoratingProxy = (decoratingProxy && !advised.isInterfaceProxied(DecoratingProxy.class));
int nonUserIfcCount = 0;
if (addSpringProxy) {
nonUserIfcCount ;
}
if (addAdvised) {
nonUserIfcCount ;
}
if (addDecoratingProxy) {
nonUserIfcCount ;
}
Class<?>[] proxiedInterfaces = new Class<?>[specifiedInterfaces.length nonUserIfcCount];
System.arraycopy(specifiedInterfaces, 0, proxiedInterfaces, 0, specifiedInterfaces.length);
int index = specifiedInterfaces.length;
if (addSpringProxy) {
proxiedInterfaces[index] = SpringProxy.class;
index ;
}
if (addAdvised) {
proxiedInterfaces[index] = Advised.class;
index ;
}
if (addDecoratingProxy) {
proxiedInterfaces[index] = DecoratingProxy.class;
}
return proxiedInterfaces;
}
//该方法用于获取一个代理对象中的用户定义的接口,即非(Advised接口体系)之外的其他接口
public static Class<?>[] proxiedUserInterfaces(Object proxy) {
Class<?>[] proxyInterfaces = proxy.getClass().getInterfaces();
int nonUserIfcCount = 0;
if (proxy instanceof SpringProxy) {
nonUserIfcCount ;
}
if (proxy instanceof Advised) {
nonUserIfcCount ;
}
if (proxy instanceof DecoratingProxy) {
nonUserIfcCount ;
}
Class<?>[] userInterfaces = new Class<?>[proxyInterfaces.length - nonUserIfcCount];
System.arraycopy(proxyInterfaces, 0, userInterfaces, 0, userInterfaces.length);
Assert.notEmpty(userInterfaces, "JDK proxy must implement one or more interfaces");
return userInterfaces;
}
//判断两个(即将)代理出来的对象是否相同
public static boolean equalsInProxy(AdvisedSupport a, AdvisedSupport b) {
return (a == b ||
(equalsProxiedInterfaces(a, b) && equalsAdvisors(a, b) && a.getTargetSource().equals(b.getTargetSource())));
}
// 判断它哥俩的接口是否相同
public static boolean equalsProxiedInterfaces(AdvisedSupport a, AdvisedSupport b) {
return Arrays.equals(a.getProxiedInterfaces(), b.getProxiedInterfaces());
}
// 判断它哥俩的增强器(Advisor)是否相同
public static boolean equalsAdvisors(AdvisedSupport a, AdvisedSupport b) {
return Arrays.equals(a.getAdvisors(), b.getAdvisors());
}
}
JDK代理和CGLIB代理的获取代理对象方法都用使用此方法:
代码语言:javascript复制 // 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);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
AopProxyUtils
中的方法不多,但是其中的ultimateTargetClass和completeProxiedInterfaces
方法确是Spring AOP中比较重要的方法,也给了我们一个入手观察Spring AOP真正实现过程的一个突破口;我认为这个,才是AopProxyUtils
给我们的价值;
AopContext
这个工具类就更简单,它代表AOP的上下文。主要是提供我们访问上下文中当前AOP对象的快速方法。
代码语言:javascript复制public abstract class AopContext {
// 一个ThreadLocal,和当前上下文绑定的AOP对象
private static final ThreadLocal<Object> currentProxy = new NamedThreadLocal<>("Current AOP proxy");
// public方法,调用者可以在任何地方获取到当前上下文中的AOP代理对象。
// 请注意:这个和exposeProxy参数有关,只有为true了才生效,默认都是false的
public static Object currentProxy() throws IllegalStateException {
Object proxy = currentProxy.get();
if (proxy == null) {
throw new IllegalStateException(
"Cannot find current proxy: Set 'exposeProxy' property on Advised to 'true' to make it available.");
}
return proxy;
}
@Nullable
static Object setCurrentProxy(@Nullable Object proxy) {
Object old = currentProxy.get();
if (proxy != null) {
currentProxy.set(proxy);
}
else {
currentProxy.remove();
}
return old;
}
}
备注:这个工具类主要是和属性
exposeProxy
相关,让我们能够快捷的获取到AOP代理对象,而不是this对象。这个在事务不生效原因大解读的博文了得到了应用
AutoProxyUtils
为自动代理组件准备的工具类。主要用于框架内部使用(AbstractAutoProxyCreator
)
public abstract class AutoProxyUtils {
// org.springframework.aop.framework.autoproxy.AutoProxyUtils.preserveTargetClass
// preserve:保护的 保留的
// determine:查明 测定
public static final String PRESERVE_TARGET_CLASS_ATTRIBUTE =
Conventions.getQualifiedAttributeName(AutoProxyUtils.class, "preserveTargetClass");
// org.springframework.aop.framework.autoproxy.AutoProxyUtils.originalTargetClass
public static final String ORIGINAL_TARGET_CLASS_ATTRIBUTE =
Conventions.getQualifiedAttributeName(AutoProxyUtils.class, "originalTargetClass");
// 判断该beanName是否应该被代理
// `AbstractAutoProxyCreator`里就有判断是否能够被代理。 如果能够被代理,那就采用CGLIB的代理方式了
// 往里setAttr,目前只有`ConfigurationClassPostProcessor`对config配置类进行增强的时候
//
public static boolean shouldProxyTargetClass(ConfigurableListableBeanFactory beanFactory, @Nullable String beanName) {
// 容器内存在这个Bean,并且这个Bean的定义信息里面属性值`PRESERVE_TARGET_CLASS_ATTRIBUTE`必须是true才行 说明才能被代理
if (beanName != null && beanFactory.containsBeanDefinition(beanName)) {
BeanDefinition bd = beanFactory.getBeanDefinition(beanName);
return Boolean.TRUE.equals(bd.getAttribute(PRESERVE_TARGET_CLASS_ATTRIBUTE));
}
return false;
}
// 看看这个Bean定义的TargetClass
// 如果Bean定义信息里面有ORIGINAL_TARGET_CLASS_ATTRIBUTE这个字段,那就不用getType()了
// 以及ScopedProxyUtils创建和Scope有关的代理类的时候,其余地方都不会设置此属性
@Nullable
public static Class<?> determineTargetClass(ConfigurableListableBeanFactory beanFactory, @Nullable String beanName) {
if (beanName == null) {
return null;
}
if (beanFactory.containsBeanDefinition(beanName)) {
BeanDefinition bd = beanFactory.getMergedBeanDefinition(beanName);
Class<?> targetClass = (Class<?>) bd.getAttribute(ORIGINAL_TARGET_CLASS_ATTRIBUTE);
if (targetClass != null) {
return targetClass;
}
}
return beanFactory.getType(beanName);
}
//Expose the given target class for the specified bean, if possible
// 就是在它的Bean定义信息里面,设置一个ORIGINAL_TARGET_CLASS_ATTRIBUTE属性,然后吧targetClass类型放进去
// 也是子啊`AbstractAutoProxyCreator`创建代理的时候会这只进去的
static void exposeTargetClass(ConfigurableListableBeanFactory beanFactory, @Nullable String beanName,
Class<?> targetClass) {
if (beanName != null && beanFactory.containsBeanDefinition(beanName)) {
beanFactory.getMergedBeanDefinition(beanName).setAttribute(ORIGINAL_TARGET_CLASS_ATTRIBUTE, targetClass);
}
}
}
AspectJAopUtils
相比于AopUtils
,AspectJAopUtils
是专门针对于AspectJ advisors
的工具类。(当然AspectJ也是当下的主流方式)
public abstract class AspectJAopUtils {
//拿到AspectJ的优先信息:AspectJPrecedenceInformation 这个就接口保存着
@Nullable
public static AspectJPrecedenceInformation getAspectJPrecedenceInformationFor(Advisor anAdvisor) {
if (anAdvisor instanceof AspectJPrecedenceInformation) {
return (AspectJPrecedenceInformation) anAdvisor;
}
Advice advice = anAdvisor.getAdvice();
if (advice instanceof AspectJPrecedenceInformation) {
return (AspectJPrecedenceInformation) advice;
}
return null;
}
// Advisor 是否是前置通知类型~~~~(Advisor都持有一个advice嘛)
public static boolean isBeforeAdvice(Advisor anAdvisor) {
AspectJPrecedenceInformation precedenceInfo = getAspectJPrecedenceInformationFor(anAdvisor);
if (precedenceInfo != null) {
return precedenceInfo.isBeforeAdvice();
}
return (anAdvisor.getAdvice() instanceof BeforeAdvice);
}
// Advisor 是否是后置通知类型~~~~(Advisor都持有一个advice嘛)
public static boolean isAfterAdvice(Advisor anAdvisor) {
AspectJPrecedenceInformation precedenceInfo = getAspectJPrecedenceInformationFor(anAdvisor);
if (precedenceInfo != null) {
return precedenceInfo.isAfterAdvice();
}
return (anAdvisor.getAdvice() instanceof AfterAdvice);
}
}
AspectJProxyUtils
同样的,它相对于AopProxyUtils
,它只是专门处理AspectJ代理对象的工具类。
public abstract class AspectJProxyUtils {
// 判断,该Advisor是否是AspectJ的的增强器
private static boolean isAspectJAdvice(Advisor advisor) {
return (advisor instanceof InstantiationModelAwarePointcutAdvisor ||
advisor.getAdvice() instanceof AbstractAspectJAdvice ||
(advisor instanceof PointcutAdvisor &&
((PointcutAdvisor) advisor).getPointcut() instanceof AspectJExpressionPointcut));
}
// 只提供这么一个公共方法,但是这个方法都还是非常重要的。 Capable:有能力的
// 它在自动代理创建器`AspectJAwareAdvisorAutoProxyCreator#extendAdvisors`方法中有调用(重要~~~)
// 在AspectJProxyFactory#addAdvisorsFromAspectInstanceFactory方法中也有调用
// 它的作用:只要发现有AspectJ的Advisor存在,并且advisors还不包含有ExposeInvocationInterceptor.ADVISOR 那就在第一个位置上调添加一个ExposeInvocationInterceptor.ADVISOR
// 这个`ExposeInvocationInterceptor.ADVISOR`的作用:就是获取到当前的currentInvocation,也是使用的ThreadLocal
public static boolean makeAdvisorChainAspectJCapableIfNecessary(List<Advisor> advisors) {
// Don't add advisors to an empty list; may indicate that proxying is just not required
if (!advisors.isEmpty()) {
boolean foundAspectJAdvice = false;
for (Advisor advisor : advisors) {
// Be careful not to get the Advice without a guard, as
// this might eagerly instantiate a non-singleton AspectJ aspect
if (isAspectJAdvice(advisor)) {
foundAspectJAdvice = true;
}
}
if (foundAspectJAdvice && !advisors.contains(ExposeInvocationInterceptor.ADVISOR)) {
advisors.add(0, ExposeInvocationInterceptor.ADVISOR);
return true;
}
}
return false;
}
}