微信搜索【程序员囧辉】,关注这个坚持分享技术干货的程序员。
目录
代码块1:ReflectiveMethodInvocation 构造函数
代码块2:ReflectiveMethodInvocation#proceed()
代码块4:ExposeInvocationInterceptor#invoke
代码块5:AspectJAroundAdvice#invoke
代码块8:invokeAdviceMethodWithGivenArgs
前言
在上篇文章中,我们介绍了 AOP 代理的创建:Spring AOP源码学习:创建 AOP 代理,本文将介绍最后的一个重要内容:使用了 AOP 代理的方法的一次完整调用流程。
正文
关于使用的 AOP 增强方式,本文以最常使用的 @Around 作为例子进行介绍,如下代码。
@Aspect
@Component
public class LogInterceptor {
@Pointcut("execution(* com.joonwhee.open.service..*.*(..))")
public void pointcut() {
}
@Around("pointcut()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
Object[] args = pjp.getArgs();
try {
System.out.println("入参=" + JSON.toJSONString(args));
long start = System.currentTimeMillis();
Object result = pjp.proceed();
System.out.println("耗时=" + (System.currentTimeMillis() - start));
System.out.println("回参=" + JSON.toJSONString(result));
return result;
} catch (Exception e) {
return "";
}
}
}
关于被代理的方法,使用下面的 getName(String name) 作为例子进行介绍,如下代码。
@Service
public class UserServiceImpl implements UserService {
private static final Logger LOGGER = LoggerFactory.getLogger(UserServiceImpl.class);
@Override
public String getName(String name) {
LOGGER.info("UserServiceImpl#getName入参, name={}", name);
String result = "name: " + name;
LOGGER.info("UserServiceImpl#getName回参, result={}", result);
return result;
}
}
当我们调用了被 AOP 代理的方法时,使用 JDK 动态代理会走到 JdkDynamicAopProxy#invoke 方法,使用 CBLIB 代理会走到 DynamicAdvisedInterceptor#intercept 方法,两者的内容基本一样,这里就拿更常见的 JdkDynamicAopProxy#invoke 方法来介绍。
JdkDynamicAopProxy#invoke
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
Object oldProxy = null;
boolean setProxyContext = false;
// 1.advised就是proxyFactory,而targetSource持有被代理对象的引用
TargetSource targetSource = this.advised.targetSource;
Class<?> targetClass = null;
Object target = null;
try {
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.
// 目标不实现equals(Object)方法本身。
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.
return hashCode();
} else if (method.getDeclaringClass() == DecoratingProxy.class) {
// There is only getDecoratedClass() declared -> dispatch to proxy config.
// 只有getDecoratedClass()声明 - > dispatch到代理配置。
return AopProxyUtils.ultimateTargetClass(this.advised);
} else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// Service invocations on ProxyConfig with the proxy config...
// ProxyConfig上的服务调用与代理配置...
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
// 有时候目标对象内部的自我调用将无法实施切面中的增强则需要通过此属性暴露代理
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// 2.拿到我们被代理的对象实例
target = targetSource.getTarget();
if (target != null) {
targetClass = target.getClass();
}
// Get the interception chain for this method.
// 3.获取拦截器链:例如使用@Around注解时会找到AspectJAroundAdvice,还有ExposeInvocationInterceptor
List<Object