跳转查看ProxyFactory的使用
ProxyFactory
是Spring-AOP中非常核心的类,如果不懂ProxyFactory
,就无法彻底理解Spring-AOP
1. 创建代理入口:ProxyFactory#getProxy
ProxyFactory#getProxy()
public Object getProxy() {
return createAopProxy().getProxy();
}
ProxyFactory#createAopProxy()
- activate()`方法可以忽略: 只是回调了ProxyFactory的Listener, Spring未使用到该扩展点
getAopProxyFactory()
:AopProxyFactory
是一个 接口, 只有一个实现类DefaultAopProxyFactory
所以继续跟踪DefaultAopProxyFactory
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
2. DefaultAopProxyFactory
DefaultAopProxyFactory#createProxy()
if
中有三个判断条件
-isOptimize()
: 默认false, 是否考虑优先采用Cglib
, 因为Cglib的性能高于JDK的Proxy
-isProxyTargetClass()
: 默认false, 是否基于类的代理
-hasNoUserSuppliedProxyInterfaces()
: 根据被代理类的接口判断, 如果没有实现任何接口, 那么也采用Cglib
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
// 1.当前类就是接口
// 2.当前类就是Proxy对象: 这种情况很罕见
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
本次以跟踪JdkDynamicAopProxy
的源码为主,ObjenesisCglibAopProxy
和JdkDynamicAopProxy
的逻辑大同小异
JdkDynamicAopProxy
相对来说简单易读一些
3. JdkDynamicAopProxy
1. 构造方法
构造参数的 config
实际上就是 ProxyFactory
, ProxyFactory
继承了 AdvisedSupport
等价为: this.advised = proxyFactory
public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
// 忽略异常判断...
this.advised = config;
}
2. JdkDynamicAopProxy#getProxy()
创建代理
直接调用了Jdk的Proxy
类创建了代理对象,且第三个参数InvocationHandler
就是当前对象
那么执行代理对象的任何方法都会执行到当前对象的invoke()
方法
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
// 计算出来需要实现哪些接口
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
// 看看是否有重写了equals/hashcode, 仅仅为了优化
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
// handler就是自己, 真正调用时会执行当前对象的invoke方法
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
此刻,代理对象已经创建成功了
接下来应该取分析invoke()
方法了,代理对象的任何方法执行前都会执行invoke()
方法
3. JdkDynamicAopProxy#invoke()
- 调用的是
equals()
方法,那么直接调用JdkDynamicAopProxy#equals
,不执行Aspect
增强- 调用的是
hashcode()
方法,那么直接调用JdkDynamicAopProxy#hashcode
,不执行Aspect
增强- 调用的是
DecoratingProxy#getDecoratedClass()
方法,那么直接返回当前被代理对象的class
类型
- 条件1:
this.advised.opaque == false
;
前面构造方法有说过,this.advised
其实就是proxyFactory
, 且proxyFactory
的opaque
默认就为false;
什么情况下opaque
属性需要被设置为true
呢? 当你希望Advised
接口的方法调用也被Advice
增强时, 可以给proxyFactory#opaque
设置为true- 条件2:调用的是
Advised
接口里的方法,( Spring创建代理时, 会给被代理类实现Advised
接口 ), Spring创建的代理对象都可以被强制转换为Advised
exposeProxy
是否为true ( 默认false ) ;
如果为true, 暴露当前的代理对象, 使调用者可以通过调用AopContext#currentProxy()
方法获取到当前的代理对象- 获取当前被代理对象的
class
;
值得一提的是,通常使用ProxyFactory
时,没有给targetSource
赋值, 那么targetSource
是怎么来的呢?
根据proxyFactory#setTaget
方法可知,proxyFactory
会将被代理的目标对象封装成SingletonTargetSource
赋值给targetSource
属性- 组装拦截器链, 核心方法,将
proxyFactory
中的advisor
封装成拦截器链, 对被代理对象的方法进行拦截
@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
// 1. 调用了equlas() 方法
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
return equals(args[0]);
// 2. 调用的是hashCode方法
} else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
return hashCode();
// 3. 调用的是DecoratingProxy#getDecoratedClass()方法
} else if (method.getDeclaringClass() == DecoratingProxy.class) {
return AopProxyUtils.ultimateTargetClass(this.advised);
// 4. advised的opaque属性为false && 调用的是Advised接口里的方法
} else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
// 5. 是否期望暴露当前代理的对象
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// 6. 获取被代理的对象的class, targetSource在方法最开始被赋值
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// 7. 组装拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
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();
}
Class<?> returnType = method.getReturnType();
// return this 的特殊处理
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
retVal = proxy;
} else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
return retVal;
} finally {
if (target != null && !targetSource.isStatic()) {
// ignore : 空实现
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// 还原AopContext的currentProxy
AopContext.setCurrentProxy(oldProxy);
}
}
}
4. 组装拦截器链
组装拦截器链的主要目的为:
将可以被使用的的advice
统一转换为MethodInterceptor
列表 ( List<MethodInterceptor>
)
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass)
注意:这里的this.advised
其实就是proxyFactory
,这个关键点在构造方法时也提到过
proxyFactory
中包含了所有的advisor
和advice
,还有一些其他的属性,例如exposeProxy
,frozen
等
其实给
proxyFactory
添加Advice
时,Advice
也会被包装成Advisor
附带ProxyFactory#addAdvice
源码
@Override
public void addAdvice(int pos, Advice advice) throws AopConfigException {
if (advice instanceof IntroductionInfo) {
addAdvisor(pos, new DefaultIntroductionAdvisor(advice, (IntroductionInfo) advice));
}
else if (advice instanceof DynamicIntroductionAdvice) {
throw new AopConfigException("DynamicIntroductionAdvice may only be added as part of IntroductionAdvisor");
}
else {
addAdvisor(pos, new DefaultPointcutAdvisor(advice));
}
}
5. getInterceptorsAndDynamicInterceptionAdvice
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
MethodCacheKey cacheKey = new MethodCacheKey(method);
List<Object> cached = this.methodCache.get(cacheKey);
if (cached == null) {
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
this, method, targetClass);
this.methodCache.put(cacheKey, cached);
}
return cached;
}
可以看到,这里还没有组装拦截器链条,只是有一层缓存的逻辑
真正组装拦截件器链条委托给了advisorChainFactory
6. advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class<?> targetClass) {
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) {
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
boolean match;
/*** 忽略这段逻辑, 没必要细, 这里牵扯到`AspectJ`的`Pointcut`表达式匹配的`maybeMatch`的分支
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);
/*** 忽略这段逻辑,没必要细究,因为有些`advisor`需要在运行时判断是否可以匹配
if (mm.isRuntime()) {
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}*/
else {
// 添加到 { interceptorList } 中
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
// 忽略这两个分支
else if (advisor instanceof IntroductionAdvisor) { /* ... */ }
else { /* ... */ }
}
// 返回 { interceptorList }
return interceptorList;
}
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
AdvisorAdapterRegistry 是一个适配器,用于将
Advice
接口下的实现类转换为MethodInterceptor
Advisor[] advisors = config.getAdvisors();
config
其实就是ProxyFactory
,获取ProxyFactory
的所有advisor
List<Object> interceptorList = new ArrayList<>(advisors.length);
用于作为方法结果返回的,也就是真正的执行器链对象
if (advisor instanceof PointcutAdvisor)
99%的情况下都是这个分支,例如我们直接使用
@Pointcut
注解为Aspect
声明切入点时,Aspect
就会被包装为PointcutAdvisor
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass))
isPreFiltered()
一个优化点,如果提前检查过了,那么就不再通过ClassFilter
再检查一次
在ProxyFactory使用篇章中有提到过,PointcutAdvisor
的Pointcut
可以基于类和方法判断是否进行切入,此刻就是在判断类是否匹配
match = mm.matches(method, actualClass);
判断方法是否匹配
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
将advisor转换为MethodInterceptor[]
- 如果advisor的advice本身就是
MethodInterceptor
,那么直接返回- 否则使用
AdvisorAdapterRegistry registry
适配器进行适配,将advice
转换为methodInterceptor
为什么一个advisor
可以被转换成一个MethodInterceptor[]
数组呢?
因为一个advice
可能即实现了BeforeAdvice
,又实现了AfterAdvice
,那么这个advice
就会被包装成两个MethodInterceptor
7. 回到invoke()
方法
@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
// 1. 调用了equlas() 方法
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
return equals(args[0]);
// 2. 调用的是hashCode方法
} else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
return hashCode();
// 3. 调用的是DecoratingProxy#getDecoratedClass()方法
} else if (method.getDeclaringClass() == DecoratingProxy.class) {
return AopProxyUtils.ultimateTargetClass(this.advised);
// 4. advised的opaque属性为false && 调用的是Advised接口里的方法
} else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
// 5. 是否期望暴露当前代理的对象
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// 6. 获取被代理的对象的class, targetSource在方法最开始被赋值
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// 7. 组装拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// 8. 没有适用的 { advice }
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
// 直接执行方法
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
} else {
// 9. 有适用的 { advice }, 包装为 { MethodInvocation }
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// 10. 调用 { MethodInvocation } , 获取结果
retVal = invocation.proceed();
}
Class<?> returnType = method.getReturnType();
// return this 的特殊处理
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
retVal = proxy;
} else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
// 11. 返回结果
return retVal;
} finally {
if (target != null && !targetSource.isStatic()) {
// ignore : 空实现
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// 还原AopContext的currentProxy
AopContext.setCurrentProxy(oldProxy);
}
}
}
8. ReflectiveMethodInvocation#proceed
public Object proceed() throws Throwable {
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
/*** 忽略这段逻辑,没有必要深究, 上面也提到过, 有些 { advisor } 需要在运行时判断是否匹配, 匹配上了才执行增强
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
// 运行时匹配: 匹配上了, 执行拦截器
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// 没有匹配上, 递归调用当前方法 { proceed }, 执行下一个拦截器
return proceed();
}
}
*/
else {
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
- 拦截器已经执行完了
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
// { invokeJoinpoint }其实就是通过反射直接调用了方法, 没有其他的逻辑
return invokeJoinpoint();
}
- 通过索引获取到下一个拦截器
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
- 调用
MethodInterceptor#invoke
,MethodInterceptor
的使用可以跳转查看ProxyFactory的使用
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
至此,ProxyFactory创建代理以及代理对象方法的执行已经彻底完结了