本文来分析 Spring 中 JdkDynamicAopProxy
代理对象的生成 getProxy()
方法和拦截增强 invoke
方法的相关处理逻辑。
上文我们研究过了 Pointcut
和 Advice
(Advisor
)接口以及它们在 Spring AOP
代理中的作用,并利用几个 Demo 演示了其相关关系。
为了方便阅读,把上文中的 ProxyFactoryDemo
类代码再次贴出来。
public class ProxyFactoryDemo {
public static void main(String[] args) {
// 1. 构造目标对象
Cat catTarget = new Cat();
// 2. 通过目标对象,构造 ProxyFactory 对象
ProxyFactory factory = new ProxyFactory(catTarget);
// 添加一个方法拦截器
factory.addAdvice(new MyMethodInterceptor());
// 3. 根据目标对象生成代理对象
Object proxy = factory.getProxy();
Animal cat = (Animal) proxy;
cat.eat();
}
}
源码分析
首先,我们从 ProxyFactory
类的 getProxy()
方法开始分析。
public Object getProxy() {
return createAopProxy().getProxy();
}
createAopProxy()
是 ProxyFactory
父类 ProxyCreatorSupport
中的方法的主要是根据当前的 config
信息判断是生成 JDK 动态代理还是 CGLIB 动态代理。
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
// 1. 获取 AopProxyFactory 工厂,用来创建 AopProxy 对象
// 注意 createAopProxy 的参数 this,this 就是在 ProxyFactoryDemo 中定义的 ProxyFactory 对象。
return getAopProxyFactory().createAopProxy(this);
}
/*
* 子类构造函数中如果不显示调用父类的构造函数,则会自动调用父类的无参构造函数
* 所以,ProxyCreatorSupport() 方法会在 ProxyFactory factory = new ProxyFactory(catTarget); 调用时被调用
*/
public ProxyCreatorSupport() {
this.aopProxyFactory = new DefaultAopProxyFactory();
}
public AopProxyFactory getAopProxyFactory() {
// DefaultAopProxyFactory 对象
return this.aopProxyFactory;
}
下面我们继续来看 DefaultAopProxyFactory
类中的 createAopProxy
方法。
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// config.isOptimize() 这个属性没有研究过
// 满足下面三个条件的任意一个
// 1. 如果 optimize 属性为 ture
// 2. 或者 proxyTargetClass 属性为 ture
// 3. 被代理类没有可代理的接口
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.");
}
// 如果被代理类的类型是接口,或者被代理类是 JDK 动态代理生成的代理类,则使用 JDK 动态代理
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
// 使用 CGLIB 动态代理
return new ObjenesisCglibAopProxy(config);
}
else {
// 使用 JDK 动态代理
return new JdkDynamicAopProxy(config);
}
}
ObjenesisCglibAopProxy
类在下一篇文章讲解,先来看 JdkDynamicAopProxy
类的 getProxy()
方法。
public Object getProxy() {
return getProxy(ClassUtils.getDefaultClassLoader());
}
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
// 得到所有需要代理的接口
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
// 查找被代理的接口中是否包含 equals 和 hashCode 方法,如果有,则在代理类中进行相应的标记,
// 从而在 invoke 方法中直接调用相关的方法,避免递归调用导致栈溢出
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
// 这里就是我们熟悉的 Proxy.newProxyInstance 方法了,用来生成 JDK 动态代理对象。
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
// advised 就是在 ProxyFactoryDemo 中定义的 ProxyFactory 对象。
this.advised = config;
}
AopProxyUtils
类中的的 completeProxiedInterfaces()
方法需要讲解下。
/**
* 返回要为给定 AOP 配置代理的完整接口集。
* 始终添加 SpringProxy 接口
* 如果 opaque 标记为 false,则始终添加 Advised 接口
* @param advised 代理配置
* @param decoratingProxy 为 ture 则添加 DecoratingProxy 接口
*/
static Class<?>[] completeProxiedInterfaces(AdvisedSupport advised, boolean decoratingProxy) {
// 1. 获取到所有需要被代理的接口
Class<?>[] specifiedInterfaces = advised.getProxiedInterfaces();
// 如果被代理的接口集合中没有 SpringProxy 接口,则需要添加 SpringProxy 接口到被代理集合集合中
boolean addSpringProxy = !advised.isInterfaceProxied(SpringProxy.class);
// 如果 opaque 为 false(默认是 false),且被代理的接口集合中没有 Advised 接口,则需要添加 Advised 接口到被代理集合集合中
boolean addAdvised = !advised.isOpaque() && !advised.isInterfaceProxied(Advised.class);
// decoratingProxy 为 ture,且被代理的接口集合中没有 DecoratingProxy 接口,则需要添加 DecoratingProxy 接口到被代理集合集合中
boolean addDecoratingProxy = (decoratingProxy && !advised.isInterfaceProxied(DecoratingProxy.class));
// 省略添加逻辑...
return proxiedInterfaces;
}
由此,我们就知道了 JdkDynamicAopProxy
代理类的生成逻辑。
然后我们再来看 JdkDynamicAopProxy
类的 invoke
方法。
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// 不代理 equals 方法,通过 JdkDynamicAopProxy 中定义的 equals 方法进行比较
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// 不代理 hashCode 方法,调用 JdkDynamicAopProxy 中定义的 hashCode 方法
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// DecoratingProxy 接口中只有 getDecoratedClass 方法,通过下面的方法实现其逻辑
return AopProxyUtils.ultimateTargetClass(this.advised);
}
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// opaque 为 false 才可能代理 Advised 接口
// 如果 method 是在 Advised 中声明的,则直接把 method 转移到 advised 对象上调用。
// 这样就可以通过代理对象直接操作代理的配置,比如新增 Advisor。
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
if (this.advised.exposeProxy) {
// 如果需要在拦截器暴露 proxy 对象,则把 proxy 对象添加到 ThreadLocal 中
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// 获取目标对象和目标对象类型
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// 获取此方法的拦截器链,这个方法后面会进行讨论
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
if (chain.isEmpty()) {
// 如果拦截器集合为空,说明当前 method 不需要被增强,则通过反射直接调用目标对象上的方法
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// 创建 ReflectiveMethodInvocation,用来管理方法拦截器责任链
// 类似于 【Spring AOP (四) 多重代理和责任链模式】 中的 MyMethodInvocationImpl
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// 通过 invocation.proceed 驱动方法拦截器责任链的运行,并获取到返回值。
retVal = invocation.proceed();
}
// 返回 this,需要替换为 proxy 对象
Class<?> returnType = method.getReturnType();
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 (setProxyContext) {
// 把第一次调用 setCurrentProxy 返回的对象,重新设置到 ThreadLocal 中
AopContext.setCurrentProxy(oldProxy);
}
}
}
我们接下来分析一下在 invoke
方法中值得关注的地方。
advised
的 getInterceptorsAndDynamicInterceptionAdvice
方法,此方法定义在 AdvisedSupport
类中。
AdvisorChainFactory advisorChainFactory = new DefaultAdvisorChainFactory();
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
// 1. 定义 method 的 cacheKey,用来缓存结果
MethodCacheKey cacheKey = new MethodCacheKey(method);
// 2. 从缓存中获取 method 的拦截器列表
List<Object> cached = this.methodCache.get(cacheKey);
if (cached == null) {
// 3. 通过 DefaultAdvisorChainFactory的 getInterceptorsAndDynamicInterceptionAdvice 获取 method 的拦截器列表
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
this, method, targetClass);
// 4. 保存 method 的拦截器列表到缓存中
this.methodCache.put(cacheKey, cached);
}
return cached;
}
getInterceptorsAndDynamicInterceptionAdvice
方法中涉及 DefaultAdvisorChainFactory
类中的相关代码清单如下所示。
// 省略了方法中关于 Introduction 增强的处理逻辑
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class<?> targetClass) {
// // 获取一个全局唯一的 AdvisorAdapterRegistry 对象
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
// 这里的 config,就是最开始定义的 ProxyFactory 对象
// 获取到所有的 Advisor
Advisor[] advisors = config.getAdvisors();
List<Object> interceptorList = new ArrayList<>(advisors.length);
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
for (Advisor advisor : advisors) {
// 如果 advisor 是 PointcutAdvisor 类型
if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
// 如果 preFiltered 为 ture,或者目标对象类型满足 ClassFilter 的条件,则进行下面的处理
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
boolean match;
// 进行方法的静态匹配
match = mm.matches(method, actualClass);
if (match) {
// 匹配则把 advisor 中的 Advice(MethodInterceptor 是 Advice 的子接口) 添加方法拦截器列表
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
if (mm.isRuntime()) {
// 如果需要进行方法的动态匹配,则转换为 InterceptorAndDynamicMethodMatcher 类型,在 invoke 方法调用时进行动态匹配
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
// 不是 PointcutAdvisor 说明没有 Pointcut,则匹配所有方法
else {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}
getInterceptorsAndDynamicInterceptionAdvice
方法中一个容易忽略的地方就是 AdvisorAdapterRegistry
接口和其 getInterceptors
方法。
GlobalAdvisorAdapterRegistry
类的代码清单如下所示。
public final class GlobalAdvisorAdapterRegistry {
private GlobalAdvisorAdapterRegistry() {
}
/**
* 保存单个实例,以便我们给请求它的类使用。
*/
private static AdvisorAdapterRegistry instance = new DefaultAdvisorAdapterRegistry();
public static AdvisorAdapterRegistry getInstance() {
return instance;
}
static void reset() {
instance = new DefaultAdvisorAdapterRegistry();
}
}
DefaultAdvisorAdapterRegistry
类的代码清单如下所示。
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {
private final List<AdvisorAdapter> adapters = new ArrayList<>(3);
/**
* 创建一个新的 DefaultAdvisorAdapterRegistry,注册默认的 AdvisorAdapter。
*/
public DefaultAdvisorAdapterRegistry() {
registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
registerAdvisorAdapter(new AfterReturningAdviceAdapter());
registerAdvisorAdapter(new ThrowsAdviceAdapter());
}
/**
* 返回给定 advice 的包装类 advisor
* 默认至少支持如下 Advice:
* org.aopalliance.intercept.MethodInterceptor
* org.springframework.aop.MethodBeforeAdvice
* org.springframework.aop.AfterReturningAdvice
* org.springframework.aop.ThrowsAdvice
*/
@Override
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
// 如果 adviceObject 已经是 Advisor 实例,直接返回
if (adviceObject instanceof Advisor) {
return (Advisor) adviceObject;
}
// 如果 adviceObject 不是 Advice 实例,直接抛出异常
if (!(adviceObject instanceof Advice)) {
throw new UnknownAdviceTypeException(adviceObject);
}
Advice advice = (Advice) adviceObject;
if (advice instanceof MethodInterceptor) {
// MethodInterceptor 不需要 wrap
return new DefaultPointcutAdvisor(advice);
}
for (AdvisorAdapter adapter : this.adapters) {
// 检查 adapter 是否理解此 advice 对象? 即使用 Advisor 调用 getInterceptors 方法作为参数是否有效?
if (adapter.supportsAdvice(advice)) {
return new DefaultPointcutAdvisor(advice);
}
}
// 如果上面的条件都不满足,直接抛出异常
throw new UnknownAdviceTypeException(advice);
}
@Override
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List<MethodInterceptor> interceptors = new ArrayList<>(3);
Advice advice = advisor.getAdvice();
// 1. 如果 advice 是 MethodInterceptor 实例,直接添加到拦截器列表
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
}
// 2. 如果存在 adapter可以把 advisor 转换为 MethodInterceptor,也需要添加到拦截器列表
for (AdvisorAdapter adapter : this.adapters) {
if (adapter.supportsAdvice(advice)) {
interceptors.add(adapter.getInterceptor(advisor));
}
}
// 拦截器列表为空,则抛出异常
if (interceptors.isEmpty()) {
throw new UnknownAdviceTypeException(advisor.getAdvice());
}
return interceptors.toArray(new MethodInterceptor[0]);
}
@Override
public void registerAdvisorAdapter(AdvisorAdapter adapter) {
this.adapters.add(adapter);
}
}
我们继续来看 AdvisorAdapter
的相关实现类中的 getInterceptor
方法。
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {
@Override
public boolean supportsAdvice(Advice advice) {
return (advice instanceof MethodBeforeAdvice);
}
@Override
public MethodInterceptor getInterceptor(Advisor advisor) {
MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
// 返回 MethodInterceptor 接口实现类 MethodBeforeAdviceInterceptor
return new MethodBeforeAdviceInterceptor(advice);
}
}
class AfterReturningAdviceAdapter implements AdvisorAdapter, Serializable {
@Override
public boolean supportsAdvice(Advice advice) {
return (advice instanceof AfterReturningAdvice);
}
@Override
public MethodInterceptor getInterceptor(Advisor advisor) {
AfterReturningAdvice advice = (AfterReturningAdvice) advisor.getAdvice();
// 返回 MethodInterceptor 接口实现类 AfterReturningAdviceInterceptor
return new AfterReturningAdviceInterceptor(advice);
}
}
class ThrowsAdviceAdapter implements AdvisorAdapter, Serializable {
@Override
public boolean supportsAdvice(Advice advice) {
return (advice instanceof ThrowsAdvice);
}
@Override
public MethodInterceptor getInterceptor(Advisor advisor) {
// 返回 MethodInterceptor 接口实现类 ThrowsAdviceInterceptor
return new ThrowsAdviceInterceptor(advisor.getAdvice());
}
}
最后,我们需要分析一下 ReflectiveMethodInvocation
类中 proceed
的逻辑,proceed
方法驱动责任链模式的运行。
/**
* 当前拦截器列表索引,表示当前已经运行到第几个 MethodInterceptor
*/
private int currentInterceptorIndex = -1;
public Object proceed() throws Throwable {
// 如果拦截器列表已经执行完毕,则调用目标对象的目标方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
// 获取责任链中的下一个 MethodInterceptor,用来对目标方法做增强处理
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// 如果 interceptorOrInterceptionAdvice 是 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 {
// 方法动态匹配失败,则驱动责任链向前运行
return proceed();
}
}
else {
// 如果目标方法不需要动态匹配,则直接调用 MethodInterceptor 的 invoke 方法,对目标方法做增强处理。
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
至此我们可以得知,Spring AOP 代理 是由如下两个核心接口实现的。
MethodInterceptor
接口中的invoke
方法对目标方法做代理(增强)处理。MethodInvocation
接口中的proceed()
方法通过责任链模式对目标方法做多重代理。在其实现类ReflectiveMethodInvocation
中实现此逻辑。
Spring 中的 JDK AOP 代理类 JdkDynamicAopProxy
到这里就基本说完了,下一篇我们讲解 CGLIB AOP 代理类 ObjenesisCglibAopProxy
类。
(正文完)
扩展阅读
- Spring AOP (一) 简介
- Spring AOP (二) JDK 动态代理
- Spring AOP (三) CGLIB 动态代理
- Spring AOP (四) 多重代理和责任链模式
- Spring AOP(五)切入点和通知
喜欢本文的朋友们,欢迎关注微信公众号【程序员小课堂】,阅读更多精彩内容!