AOP基础知识
AOP基础知识,详情见: https://blog.csdn.net/sinat_32502451/article/details/142291052
AOP 源码,详情见: https://blog.csdn.net/sinat_32502451/article/details/142291110
ProceedingJoinPoint
在上面的示例中,运用到了 ProceedingJoinPoint 。
ProceedingJoinPoint 是继承 JoinPoint(连接点) 的类。
从以上示例代码看出, ProceedingJoinPoint拥有 JoinPoint(连接点)的特性,
可以获取类的信息,包括类名、方法名、参数等(joinPoint.getArgs()),
还可以执行目标对象方法的逻辑(joinPoint.proceed())。
代码: org.aspectj.lang.ProceedingJoinPoint
/**
* ProceedingJoinPoint 继承 JoinPoint(连接点) .
* ProceedingJoinPoint 公开了progress(..)方法,以支持@AJ aspects.
*
*/
public interface ProceedingJoinPoint extends JoinPoint {
/**
* joinpoint需要知道它的AroundClosure,以便proceed可以委托给closure.run()
*
*/
void set$AroundClosure(AroundClosure arc);
/**
* 继续下一个advice或目标方法调用
*
*/
public Object proceed() throws Throwable;
/**
* 继续下一个advice或目标方法调用
*
*/
public Object proceed(Object[] args) throws Throwable;
}
ReflectiveMethodInvocation的proceed
不管是 @Pointcut 还是 @Around(环绕通知,包含前置和后置两个) 都会调用这个 proceed 方法。
代码: org.springframework.aop.framework.ReflectiveMethodInvocation#proceed
@Override
@Nullable
public Object proceed() throws Throwable {
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
//以下会调用 Joinpoint(连接点)
// 通过 invokeJoinpoint 的调用, 可以拿到目标方法的返回值。
//注意: 这里的 invokeJoinpoint() 调用的是
// org.springframework.aop.framework.CglibAopProxy.CglibMethodInvocation#invokeJoinpoint
//并不是自身的 invokeJoinpoint()方法。
return invokeJoinpoint();
}
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
return proceed();
}
}
else {
// 拦截器调用方法。@Around 环绕通知的前置和后置都会走这里
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
CglibAopProxy.CglibMethodInvocation
调用 joinPoint.proceed(); 这一行代码后,最后会调用这里的 Cglib 动态代理。
Cglib 动态代理,调用连接点的方法。
通过 invokeJoinpoint 的调用, 可以拿到目标方法的返回值。
代码: org.springframework.aop.framework.CglibAopProxy.CglibMethodInvocation#invokeJoinpoint
private static class CglibMethodInvocation extends ReflectiveMethodInvocation {
private final MethodProxy methodProxy;
private final boolean publicMethod;
public CglibMethodInvocation(Object proxy, @Nullable Object target, Method method,
Object[] arguments, @Nullable Class<?> targetClass,
List<Object> interceptorsAndDynamicMethodMatchers, MethodProxy methodProxy) {
super(proxy, target, method, arguments, targetClass, interceptorsAndDynamicMethodMatchers);
this.methodProxy = methodProxy;
this.publicMethod = Modifier.isPublic(method.getModifiers());
}
/**
* 调用 JoinPoint(连接点) 的方法
*/
@Override
protected Object invokeJoinpoint() throws Throwable {
if (this.publicMethod) {
// 通过这里的调用, 可以拿到目标方法的返回值。
return this.methodProxy.invoke(this.target, this.arguments);
}
else {
return super.invokeJoinpoint();
}
}
}
CglibAopProxy.DynamicAdvisedInterceptor
代码: org.springframework.aop.framework.CglibAopProxy.DynamicAdvisedInterceptor
调用 JoinPoint(连接点) 的方法后,会进行后置通知,调用 CglibAopProxy.DynamicAdvisedInterceptor。
/**
* 通用AOP回调。当目标是动态的或代理未冻结时使用。
*
*/
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
private final AdvisedSupport advised;
public DynamicAdvisedInterceptor(AdvisedSupport advised) {
this.advised = advised;
}
@Override
@Nullable
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Object target = null;
TargetSource targetSource = this.advised.getTargetSource();
try {
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);
Object retVal;
// 这里面的逻辑,重点看看。
// 检查是否没有真正的advice,只是对目标的反射调用。
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
// 我们可以跳过创建 MethodInvocation:直接调用目标。
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = methodProxy.invoke(target, argsToUse);
}
else {
// 创建一个方法调用。
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
AopContext.setCurrentProxy(oldProxy);
}
}
}
调用的方法栈:
这些代码也可以看看。
processReturnType:394, CglibAopProxy (org.springframework.aop.framework)
access$000:84, CglibAopProxy (org.springframework.aop.framework)
intercept:690, CglibAopProxy$DynamicAdvisedInterceptor (org.springframework.aop.framework)
getValue:-1, TestController$$EnhancerBySpringCGLIB$$682df634 (com.example.demo.controller)
invoke:-1, GeneratedMethodAccessor68 (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:497, Method (java.lang.reflect)
doInvoke:209, InvocableHandlerMethod (org.springframework.web.method.support)
invokeForRequest:136, InvocableHandlerMethod (org.springframework.web.method.support)
invokeAndHandle:102, ServletInvocableHandlerMethod (org.springframework.web.servlet.mvc.method.annotation)
invokeHandlerMethod:891, RequestMappingHandlerAdapter (org.springframework.web.servlet.mvc.method.annotation)
handleInternal:797, RequestMappingHandlerAdapter (org.springframework.web.servlet.mvc.method.annotation)
handle:87, AbstractHandlerMethodAdapter (org.springframework.web.servlet.mvc.method)
doDispatch:991, DispatcherServlet (org.springframework.web.servlet)
doService:925, DispatcherServlet (org.springframework.web.servlet)
processRequest:974, FrameworkServlet (org.springframework.web.servlet)
doGet:866, FrameworkServlet (org.springframework.web.servlet)
service:635, HttpServlet (javax.servlet.http)
service:851, FrameworkServlet (org.springframework.web.servlet)
service:742, HttpServlet (javax.servlet.http)
internalDoFilter:231, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
doFilter:52, WsFilter (org.apache.tomcat.websocket.server)
internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
doFilterInternal:99, RequestContextFilter (org.springframework.web.filter)
doFilter:107, OncePerRequestFilter (org.springframework.web.filter)
internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
doFilterInternal:109, HttpPutFormContentFilter (org.springframework.web.filter)
doFilter:107, OncePerRequestFilter (org.springframework.web.filter)
internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
doFilterInternal:93, HiddenHttpMethodFilter (org.springframework.web.filter)
doFilter:107, OncePerRequestFilter (org.springframework.web.filter)
internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
doFilterInternal:200, CharacterEncodingFilter (org.springframework.web.filter)
doFilter:107, OncePerRequestFilter (org.springframework.web.filter)
internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
invoke:198, StandardWrapperValve (org.apache.catalina.core)
invoke:96, StandardContextValve (org.apache.catalina.core)
invoke:493, AuthenticatorBase (org.apache.catalina.authenticator)
invoke:140, StandardHostValve (org.apache.catalina.core)
invoke:81, ErrorReportValve (org.apache.catalina.valves)
invoke:87, StandardEngineValve (org.apache.catalina.core)
service:342, CoyoteAdapter (org.apache.catalina.connector)
service:800, Http11Processor (org.apache.coyote.http11)
process:66, AbstractProcessorLight (org.apache.coyote)
process:806, AbstractProtocol$ConnectionHandler (org.apache.coyote)
doRun:1498, NioEndpoint$SocketProcessor (org.apache.tomcat.util.net)
run:49, SocketProcessorBase (org.apache.tomcat.util.net)
runWorker:1142, ThreadPoolExecutor (java.util.concurrent)
run:617, ThreadPoolExecutor$Worker (java.util.concurrent)
run:61, TaskThread$WrappingRunnable (org.apache.tomcat.util.threads)
run:745, Thread (java.lang)
标签:web,13,catalina,--,Object,springframework,源码,apache,org
From: https://www.cnblogs.com/expiator/p/18446433