这篇文章主要讲解了“Spring Framework中DefaultAdvisorChainFactory类案例分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Spring Framework中DefaultAdvisorChainFactory类案例分析”吧!
Spring版本是5.0.4.release.
JdkDynamicAopProxy中使用到了拦截器链,如下List-1,advised是ProxyFactory,而方法getInterceptorsAndDynamicInterceptionAdvice则是在其父类AdvisedSupport中。
List-1
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { ... // Get the interception chain for this method. List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); ... }
如下List-2,advisorChainFactory是DefaultAdvisorChainFactory
List-2
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; }
getInterceptorsAndDynamicInterceptionAdvice的方法实现如下List-3所示,会将Advisor转换为Interceptor,List-3中的registry是DefaultAdvisorAdapterRegistry。
List-3
public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializable { @Override public List<Object> getInterceptorsAndDynamicInterceptionAdvice( Advised config, Method method, @Nullable Class<?> targetClass) { ... Interceptor[] interceptors = registry.getInterceptors(advisor); ... return interceptorList; } ...
如下List-4所示,构造方法中注册了Adapter,而后getInterceptors方法中会使用模板模式将advisor中的advice转换为MethodInterceptor。
List-4
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable { private final List<AdvisorAdapter> adapters = new ArrayList<>(3); public DefaultAdvisorAdapterRegistry() { registerAdvisorAdapter(new MethodBeforeAdviceAdapter()); registerAdvisorAdapter(new AfterReturningAdviceAdapter()); registerAdvisorAdapter(new ThrowsAdviceAdapter()); } @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]); } ...
来看个例子,如下List-5所示,MethodBeforeAdviceAdapter的supportsAdvice方法中判断是否是MethodBeforeAdvice;getInterceptor方法中将advice封装到MethodBeforeAdviceInterceptor中。
List-5
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方法,会先调用MethodBeforeAdvice的before方法,之后才会执行MethodInvocation的invoke方法。
List-6
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable { private final MethodBeforeAdvice advice; public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) { Assert.notNull(advice, "Advice must not be null"); this.advice = advice; } @Override public Object invoke(MethodInvocation mi) throws Throwable { this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis()); return mi.proceed(); } }
整体来看DefaultAdvisorChainFactory会将我们的advice转换为MethodInerceptor,而不同的Advice实现,对应的MethodInterceptor实现也不一样,进而实现Before、After的拦截实现。
从Spring容器中获取bean的时候,用于这个bean的拦截器就构造好,且与这个目标类封装在一起,之后当调用这个目标类的方法时,就会再次构造拦截器链,为什么会再次构造拦截器链是因为有些拦截器只作用与目标类的部分方法,不过这个基于方法层面的拦截器还是做了缓存的。
感谢各位的阅读,以上就是“Spring Framework中DefaultAdvisorChainFactory类案例分析”的内容了,经过本文的学习后,相信大家对Spring Framework中DefaultAdvisorChainFactory类案例分析这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。