Spring-11 AOP JDK & CGLIB 动态代理详解

Spring 源码系列文章会遵循由浅入深,由易到难,由宏观到微观的原则,目标是尽量降低学习难度,而不是一上来就迷失在源码当中. 文章会从一个场景作为出发点,针对性的目的性极强的针对该场景对 Spring 的实现原理,源码进行探究学习。该系列文章会让你收获什么? 从对 Spring 的使用者成为 Spring 专家。该文章会同步在微信公众号 【DevXJava】, 方便在微信客户端阅读。

ProxyFactory & AopProxyFactory & AopProxy & 代理对象之间的关系

ProxyFactory 中的重要属性有 targetSource 封装了目标对象, interfaces 目标对象类型的接口 , advisors 封装了切面和连接点信息。在创建代理对象的过程中会将 ProxyFactory 对象层层传递以保留 AOP 的相关配置信息。






JDK 动态代理

jdk 代理使用的是 JdkDynamicAopProxy 创建的。JdkDynamicAopProxy 本身就是 InvocationHandler 的实现。在创建代理时就是使用 jdk Proxy 创建代理对象。


@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) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
// Check whether we only have one InvokerInterceptor: that is,
// no real advice, but just reflective invocation of the target.
if (chain.isEmpty() && CglibMethodInvocation.isMethodProxyCompatible(method)) {
// We can skip creating a MethodInvocation: just invoke the target directly.
// Note that the final invoker must be an InvokerInterceptor, so we know
// it does nothing but a reflective operation on the target, and no hot
// swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
try {
retVal = methodProxy.invoke(target, argsToUse);
}
catch (CodeGenerationException ex) {
CglibMethodInvocation.logFastClassGenerationFailure(method);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
}
else {
// We need to create a method invocation...
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) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}

DevX 会持续分享 Java 技术干货,如果你觉得本文对你有帮助希望你可以分享给更多的朋友看到。该文章会同步在微信公众号 【DevXJava】, 方便在微信客户端阅读。

DevX 不止于技术


本篇文章来源于微信公众号: DevXJava



微信扫描下方的二维码阅读本文

此作者没有提供个人介绍
最后更新于 2023-05-28