java开发AOP基础JdkDynamicAopProxy
作者:王侦
1.示例代码
public class Main { public static void main(String[] args) { //1. 创建被代理对象 Cat cat = new Cat(); System.out.println("--------------------"); //2. 创建Spring 代理工厂对象 ProxyFactory // ProxyFactory 是Config + Factory 的存在,持有Aop操作所有的生产资料 ProxyFactory proxyFactory = new ProxyFactory(cat); //3. 添加方法拦截器 MyPointcut pointcut = new MyPointcut(); proxyFactory.addAdvisor(new DefaultPointcutAdvisor(pointcut, new MethodInterceptor01())); proxyFactory.addAdvisor(new DefaultPointcutAdvisor(pointcut, new MethodInterceptor02())); //4. 获取代理对象 Animal proxy = (Animal) proxyFactory.getProxy(); proxy.eat(); System.out.println("--------------------"); proxy.go(); } }
结果,只有eat()方法被加强了:
--------------------
methodInterceptor01 begin
MethodInterceptor02 begin
猫猫 吃 猫粮!
MethodInterceptor02 end
methodInterceptor01 end
--------------------
猫猫 跑跑~!
切点:
- 1)匹配所有类
- 2)匹配eat()方法
public class MyPointcut implements Pointcut { @Override public ClassFilter getClassFilter() { return new ClassFilter() { @Override public boolean matches(Class<?> clazz) { return true; } }; } @Override public MethodMatcher getMethodMatcher() { return new MethodMatcher() { @Override public boolean matches(Method method, Class<?> targetClass) { if(method.getName().equals("eat")) { return true; } return false; } @Override public boolean isRuntime() { return false; } @Override public boolean matches(Method method, Class<?> targetClass, Object... args) { return false; } }; } }
2.ProxyFactory#getProxy()
public Object getProxy() { //主要分析 JdkDynamicAopProxy, 假设 createAopProxy 返回的就是 JdkDynamicAopProxy return createAopProxy().getProxy(); }
2.1 ProxyCreatorSupport#createAopProxy
protected final synchronized AopProxy createAopProxy() { if (!this.active) { activate(); } return getAopProxyFactory().createAopProxy(this); }
/** * config 就是我们的ProxyFactory对象,咱们说过 ProxyFactory * 它是一个配置管理对象,保存着 创建 代理对象所有的生产资料呢。 */ @Override public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { //条件一:config.isOptimize() 暂且不管 //条件二:config.isProxyTargetClass() true 强制使用cglib 动态代理 //条件三:hasNoUserSuppliedProxyInterfaces(config) // 说明被代理对象 没有实现任何接口,没有办法使用JDK动态代理,只能使用cglib动态代理 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."); } //条件成立:说明targetClass是接口 或者 已经是被代理过的类型了,只能使用Jdk动态代理 if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); } return new ObjenesisCglibAopProxy(config); } else { //执行到else 什么情况? targetClass 是实现了接口情况下, // 会走这个分支!咱们大多数情况都是 面向接口 编程,所以主要分析 JdkDynamicAopProxy return new JdkDynamicAopProxy(config); } }
2.2 JdkDynamicAopProxy#getProxy()
@Override public Object getProxy() { return getProxy(ClassUtils.getDefaultClassLoader()); } @Override 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 方法,如果有,就打个标记。 findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); // classLoader :类加载器 // proxiedInterfaces :生成的代理类 需要 实现的接口集合 // this? : JdkDynamicAopProxy 该类 实现了 InvocationHandler 接口 // 该方法最终会返回一个 代理类 对象。 return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); }
生成的代理类类似于下面所示:
public final class $proxy0 extends Proxy implements Animal { private static Method m1; private static Method m3; private static Method m2; private static Method m0; public $proxy0(InvocationHandler var1) throws { super(var1); } public final boolean equals(Object var1) throws { try { return (Boolean)super.h.invoke(this, m1, new Object[]{var1}); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException(var4); } } public final void eat() throws { try { super.h.invoke(this, m3, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } }
所有方法最后都经由InvocationHandler#invoke进行处理
3.调用流程JdkDynamicAopProxy#invoke
/** * Implementation of {@code InvocationHandler.invoke}. * <p>Callers will see exactly the exception thrown by the target, * unless a hook method throws an exception. * * @param proxy 代理对象 * * @param method 目标对象的方法 * * @param args 目标对象方法对应的参数 */ @Override @Nullable public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object oldProxy = null; boolean setProxyContext = false; // 获取到创建ProxyFactory时 提供的 target TargetSource targetSource = this.advised.targetSource; // 真正的target 的一个引用 Object target = null; try { // 条件成立,说明代理类实现的哪些接口 没有定义equals方法, // 并且当前method 是 equals方法的话,就使用JdkDynamicAopProxy 提供的 equals方法。 if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { // The target does not implement the equals(Object) method itself. return equals(args[0]); } // 条件成立,说明代理类实现的哪些接口 没有定义hashCode方法, // 并且当前method 是 hashCode方法的话,就使用JdkDynamicAopProxy 提供的 equals方法。 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. 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... return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); } // 保存返回值 Object retVal; //this.advised.exposeProxy 如果是true, // 就要把当前这个代理对象,暴漏 到Aop上下文内。 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. // 根据targetSource拿到真正的目标对象 target = targetSource.getTarget(); // 获取到目标对象的 class Class<?> targetClass = (target != null ? target.getClass() : null); // Get the interception chain for this method. // 其实 这里是最关键的地方,查找适合该方法的 所有方法拦截器。 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); // Check whether we have any advice. If we don't, we can fallback on direct // reflective invocation of the target, and avoid creating a MethodInvocation. if (chain.isEmpty()) { // 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); // 直接调用目标对象的目标方法。 retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse); } // 说明有匹配当前method的方法拦截器,所以要做增强处理了。 else { // We need to create a method invocation... MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); // Proceed to the joinpoint through the interceptor chain. // 核心!注释 :ReflectiveMethodInvocation retVal = invocation.proceed(); } // Massage return value if necessary. // 方法 返回值类型 Class<?> returnType = method.getReturnType(); // 如果目标方法 返回 目标对象,这里 做个替换,返回 代理对象。 if (retVal != null && retVal == target && returnType != Object.class && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { // Special case: it returned "this" and the return type of the method // is type-compatible. Note that we can't help if the target sets // a reference to itself in another returned object. 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()) { // Must have come from TargetSource. targetSource.releaseTarget(target); } if (setProxyContext) { // 将 上次设置的proxy 再次 设置回去到 AopContext中。 // 因为当前代理对象的方法已经完事了,需要回到再上一层逻辑了, // 这里是一个恢复现场的逻辑。 // Restore old proxy. AopContext.setCurrentProxy(oldProxy); } } }
3.1获取目标方法的拦截器
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; }
DefaultAdvisorChainFactory#getInterceptorsAndDynamicInterceptionAdvice
/** * 该方法的目的,就是查找出来适合当前方法 增强! * @param config ProxyFactory,它掌握着AOP的所有资料呢 * @param method 目标对象的方法 * @param targetClass 目标对象的类型 */ @Override public List<Object> getInterceptorsAndDynamicInterceptionAdvice( Advised config, Method method, @Nullable Class<?> targetClass) { // This is somewhat tricky... We have to process introductions first, // but we need to preserve order in the ultimate list. //AdvisorAdapterRegistry 接口有两个作用,一个作用是 // 可以向里面注册 AdvisorAdapter 适配器 // 适配器目的:1. 将非Advisor 类型的 增强,包装成为Advisor // 2. 将Advisor 类型的增强 提取出来对应 MethodInterceptor AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance(); // 获取出来 ProxyFactory 内部 持有的 增强信息 // 1. addAdvice() // 2. AddAdvisor() 最终 在ProxyFactory 内 都会包装成 Advisor 的。 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) { //条件成立:说明当前advisor是包含 切点 信息的, // 所以 这个if内部的逻辑,就是做匹配算法。 if (advisor instanceof PointcutAdvisor) { // Add it conditionally. // 转换成 可以获取到切点信息的接口。 PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor; // 条件二:成立,说明当前被代理对象的class 匹配 // 当前 Advisor 成功,这一步 只是class 匹配成功。 if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) { // 获取 切点信息 的 方法匹配器 MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher(); boolean match; if (mm instanceof IntroductionAwareMethodMatcher) { if (hasIntroductions == null) { hasIntroductions = hasMatchingIntroductions(advisors, actualClass); } match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions); } else { // 如果 目标方法 匹配成功 ,那么match = true,静态匹配成功。 match = mm.matches(method, actualClass); } //静态匹配成功的话,再检查是否需要 运行时匹配。 if (match) { // 提取出来 advisor内持有的拦截器信息 MethodInterceptor[] interceptors = registry.getInterceptors(advisor); // 是否运行时匹配? if (mm.isRuntime()) { // Creating a new object instance in the getInterceptors() method // isn't a problem as we normally cache created chains. for (MethodInterceptor interceptor : interceptors) { interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm)); } } else { // 将当前advisor内部的方法拦截器 追加到 interceptorList interceptorList.addAll(Arrays.asList(interceptors)); } } } } // 引介增强 else if (advisor instanceof IntroductionAdvisor) { IntroductionAdvisor ia = (IntroductionAdvisor) advisor; if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) { Interceptor[] interceptors = registry.getInterceptors(advisor); interceptorList.addAll(Arrays.asList(interceptors)); } } // 说明当前 Advisor 匹配全部class 全部 method else { Interceptor[] interceptors = registry.getInterceptors(advisor); interceptorList.addAll(Arrays.asList(interceptors)); } } // 返回所有匹配当前method的方法拦截器 return interceptorList; }
DefaultAdvisorAdapterRegistry#getInterceptors
@Override public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException { List<MethodInterceptor> interceptors = new ArrayList<>(3); Advice advice = advisor.getAdvice(); if (advice instanceof MethodInterceptor) { interceptors.add((MethodInterceptor) advice); } 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]); }
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable { private final List<AdvisorAdapter> adapters = new ArrayList<>(3); /** * Create a new DefaultAdvisorAdapterRegistry, registering well-known adapters. */ public DefaultAdvisorAdapterRegistry() { registerAdvisorAdapter(new MethodBeforeAdviceAdapter()); registerAdvisorAdapter(new AfterReturningAdviceAdapter()); registerAdvisorAdapter(new ThrowsAdviceAdapter()); }
以MethodBeforeAdviceAdapter为例
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(); return new MethodBeforeAdviceInterceptor(advice); } }
看看 MethodBeforeAdviceInterceptor#invoke
public Object invoke(MethodInvocation mi) throws Throwable { this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis()); return mi.proceed(); }
3.2 调用ReflectiveMethodInvocation#proceed
@Override @Nullable public Object proceed() throws Throwable { // We start with an index of -1 and increment early. //条件成立:说明方法拦截器 全部都已经调用过了。 // 接下来 需要执行 目标对象的目标方法。 if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { // 调用连接点 return invokeJoinpoint(); } // 获取下一个方法拦截器 Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); // 条件成立:说明 方法拦截器 需要做 运行时匹配,很少用到运行时匹配。 if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { // Evaluate dynamic method matcher here: static part will already have // been evaluated and found to match. 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 { // Dynamic matching failed. // Skip this interceptor and invoke the next in the chain. return proceed(); } } // 大部分情况,咱们都是执行else 。 else { // It's an interceptor, so we just invoke it: The pointcut will have // been evaluated statically before this object was constructed. // 让当前方法拦截器执行,并且将 this 传递了 进去,this? MethodInvocation return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); } }
总结
- 1)ProxyFactory是所有核心要素的汇集地,包括被代理对象、增强器Advisor
- 2)JdkDynamicAopProxy作为InvocationHandler是所有方法调用的入口
- 3)调用链路
step1.JdkDynamicAopProxy#invoke
获取匹配该方法的拦截器链;
调用ReflectiveMethodInvocation;
step2.ReflectiveMethodInvocation#proceed
根据currentInterceptorIndex逐个进行调用;
最终调用至被代理的方法;
step3.MethodInterceptor#invoke(this),这里的this就是ReflectiveMethodInvocation
AspectJAroundAdvice、AspectJMethodBeforeAdvice、AspectJAfterAdvicestep4.最后反射调用至被代理的方法
以上就是java开发AOP基础JdkDynamicAopProxy的详细内容,更多关于java AOP JdkDynamicAopProxy的资料请关注脚本之家其它相关文章!