本文参考:
SpringFramework中ReflectiveMethodInvocation有什么用
DynamicAdvisedInterceptor原理
SpringAop之AdvisedSupport
从 AbstractPointcutAdvisor 开始: Spring AOP 之 Advisor、PointcutAdvisor 介绍
Spring中AOP及ReflectiveMethodInvocation逻辑简析
AOP简述
为了能够更好地将系统级别的代码抽离出来,去掉与对象的耦合,就产生了面向AOP(面向切面)。AOP全称 Aspect-Oriented
Programming , 即面向切面编程。
AspectJ
AspectJ是一个基于Java语言的AOP框架,它采用编译时增强,会将增强目标编译得到一个新的AOP代理类。
Spring AOP Spring提供的AOP框架,使用了和AspectJ一样的注解,但是通过动态生成代理类的方式生成AOP代理类。JDK Dynamic AOP Spring
AOP中AOP代理的一种实现,使用原生JDK反射和动态代理生成AOP代理,需要代理类与目标实现相同的接口。CGLib AOP
Spring AOP中AOP代理的另一种实现,使用CGLib动态生成AOP代理类,需要代理类为目标类的子类。AOP术语 Aspect 一个切面,可以理解为一个切面模块,将相关的增强内容写进同一个切面。例如:一个负责日志的切面。
Join Point 代表可以由AOP增强织入的程序执行节点。
Advice 所要做的增强处理
Pointcut 切入点,定义了将被Advice增强的一个或多个Join Point,可以使用正则表达式或模式匹配。
Target object 被增强的目标对象
Adivce的种类:Before 方法执行之前; After 方法执行之后;After-returning 方法成功执行完成之后; After-throwing 方法抛出异常之后;Around 环绕方法执行的整个周期
Spring执行AOP的过程
从代码执行角度来看,Spring AOP的执行过程分为四大步骤:
步骤一:Spring框架生成Advisor实例,可以是@Aspect,@Async等注解生成的实例,也可以是程序员自定义的AbstractAdvisor子类的实例。
步骤二:Spring框架在目标实例初始化完成后,也就是使用BeanPostProcessor的postProcessAfterInitialization方法,根据Advisor实例中切入点Pointcut的定义,选择出适合该目标对象的Advisor实例。
步骤三:Spring框架根据Advisor实例生成代理对象。
步骤四:调用方法执行过程时,Spring 框架执行Advisor实例的通知Advice逻辑。
Spring中有大量的机制都是通过AOP实现的,比如说@Async的异步调用和@Transational。此外,用户也可以使用@Aspect注解定义切面或者直接继承AbstractPointcutAdvisor来提供切面逻辑。上述这些情况下,AOP都会生成对应的Advisor实例。
AdvisedSupport
在代理方法执行时,需要调用JdkDynamicAopProxy实例,其中,有一个成员变量是AdvisedSupport
private final AdvisedSupport advised;
AdvisedSupport的类图如下:
AdvisedSupport继承ProxyConfig,主要有如下方法:
- 配置当前代理的Advisor(private List advisors)
- 配置当前代理的接口(private List<Class<?>> interfaces)
- 配置当前代理的目标对象(TargetSource targetSource)
- 提供getInterceptorsAndDynamicInterceptionAdvice方法用来获取对应代理方法对应有效的拦截器链
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
AdvisedSupport.MethodCacheKey cacheKey = new AdvisedSupport.MethodCacheKey(method);
List<Object> cached = (List)this.methodCache.get(cacheKey);
if (cached == null) {
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(this, method, targetClass);
this.methodCache.put(cacheKey, cached);
}
return cached;
}
这个方法对需要获取的拦截器链做了缓存,先取缓存,如果取不到,再调DefaultAdvisorChainFactory来执行实际的逻辑
DefaultAdvisorChainFactory中该方法如下,主要逻辑:
- 获取所有配置的advisors
- 遍历advisors数组,根据advisor是不同的类型走不同的逻辑,最终调用registry.getInterceptors转化成Interceptor返回
AdvisedSupport是用来生成拦截器chain的
IntroductionAdvisor与PointcutAdvisor都继承自Advisor,他们最本质上的区别就是,IntroductionAdvisor只能应用于类级别的拦截,只能使用Introduction型的Advice。而不能像PointcutAdvisor那样,可以使用任何类型的Pointcut,以及几乎任何类型的Advice。
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class<?> targetClass) {
// This is somewhat tricky... We have to process introductions first,
// but we need to preserve order in the ultimate list.
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
Advisor[] advisors = config.getAdvisors();
List<Object> interceptorList = new ArrayList<>(advisors.length);
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
Boolean hasIntroductions = null;
for (Advisor advisor : advisors) {
if (advisor instanceof PointcutAdvisor) {
// Add it conditionally.
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
boolean match;
if (mm instanceof IntroductionAwareMethodMatcher) {
if (hasIntroductions == null) {
hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
}
match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
}
else {
match = mm.matches(method, actualClass);
}
if (match) {
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
if (mm.isRuntime()) {
// Creating a new object instance in the getInterceptors() method
// isn't a problem as we normally cache created chains.
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
else {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}
JdkDynamicAopProxy的invoke
简单介绍一下ReflectiveMethodInvocation
ReflectiveMethodInvocation是AOP中一个重要的类,这个类在JdkDynamicAopProxy的invoke方法中使用到,可以看到在方法中,用拦截器链,代理的目标对象等参数,生成ReflectiveMethodInvocation实例
其中invoke方法主要逻辑是:
- 获取拦截器
- 如果拦截器为空,直接反射调用
- 如果不为空,创建ReflectiveMethodInvocation类,调用起proceed方法
// JdkDynamicAopProxy
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
...
// 得到所有作用在该方法上的拦截器和通知:创建代理的时候,只要切入点匹配了原始类的任意一个方法,原始对象都会被包装。而真正调用的时候,有些方法是不需要增强的,不需要的直接反射调用,需要的方法才走增强调用,所以拦截器通知需要过滤。
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// chain为空,直接反射调用;不为空创建一个CglibMethodInvocation对象,并调用proceed方法
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
} else {
MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
retVal = invocation.proceed();
}
// 如果方法返回值是原始对象,则返回代理对象,如果不是,则返回值
...
}
ReflectiveMethodInvocation的proceed
proceed方法的主要逻辑是:
- 查看是否访问到最后一个拦截器,如果是,调用invokeJoinpoint
- 如果还有拦截器,则看是否匹配,匹配的话调用拦截器的invoke,否则递归
- 如果不匹配,则直接调用该拦截器
// ReflectiveMethodInvocation 中
@Nullable
public Object proceed() throws Throwable {
// currentInterceptorIndex表示访问到第几个拦截器,如果是最后一个,那么调用invokeJoinpoint(), 利用反射方式调用目标方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return this.invokeJoinpoint();
}
// 如果还有拦截器,则用递归调用下一个拦截器
else {
Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice;
Class<?> targetClass = this.targetClass != null ? this.targetClass : this.method.getDeclaringClass();
// 如果匹配则invoke,否则proceed递归
return dm.methodMatcher.matches(this.method, targetClass, this.arguments) ? dm.interceptor.invoke(this) : this.proceed();
} else {
// 是拦截器,调用该拦截器
return ((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this);
}
}
}
小结
- Spring框架启动时根据注解等配置,生成Advisor实例和代理对象
- 方法执行时,JdkDynamicAopProxy中获取Advisor数组,遍历得到拦截器链
- 拦截器链不为空,创建ReflectiveMethodInvocation类,调用起proceed方法
- proceed方法中递归调用下一个拦截器链,或执行目标方法