博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring技术内幕3——Spring AOP原理(二)
阅读量:6287 次
发布时间:2019-06-22

本文共 8774 字,大约阅读时间需要 29 分钟。

  hot3.png

接上篇博客:Spring技术内幕3——Spring AOP原理(一)

Spring Aop最终转换成JdkDynamicAopProxy或者ObjenesisCglibAopProxy来作为入口对对象进行调用

 JdkDynamicAopProxy的入口是invoke函数,ObjenesisCglibAopProxy的入口是DynamicAdvisedInterceptor的intercept方法。其实最终都是转化成ReflectiveMethodInvocation的proceed方法。

我们接下来看proceed方法的源码:

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;			if (dm.methodMatcher.matches(this.method, this.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 {			// It's an interceptor, so we just invoke it: The pointcut will have			// been evaluated statically before this object was constructed.			return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);		}	}

     根据之前的拦截器链进行相关的匹配,我们这里可以看到,它是遍历了所有的interceptorsAndDynamicMethodMatchers,那么interceptorsAndDynamicMethodMatchers这个是哪里来的呢?我们继续回头看。

    我们在之前的配置中对ProxyFactoryBean配置了interceptorNames属性,我们在initializeAdvisorChain()初始化AdvisorChain链条的过程中,将interceptoeNames中相关的Bean对象作为Advisor注入到了

        AdvisedSupport的advisors的List集合中,我们知道ProxyFactoryBean也是AdvisedSupport的子类

因此在:

@Override	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."); } if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); } return new ObjenesisCglibAopProxy(config); } else { return new JdkDynamicAopProxy(config); } }

        这个方法中将ProxyBeanFactory已经注入了JdkDynamicAopProxy或者ObjenesisCglibAopProxy中,我们再回到CglibAopProxy或者JdkDynamicAopProxy这两个类中。

List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

   由此可以看出这边的拦截链就是调用的ProxyFactoryBean中的getInterceptorsAndDynamicInterceptionAdvice方法,而又因为ProxyFactoryBean继承于AdvisedSupport类,因此最终调用的是

DefaultAdvisorChainFactory中的getInterceptorsAndDynamicInterceptionAdvice方法。

public List getInterceptorsAndDynamicInterceptionAdvice(			Advised config, Method method, Class
targetClass) { // This is somewhat tricky... We have to process introductions first, // but we need to preserve order in the ultimate list. List interceptorList = new ArrayList(config.getAdvisors().length); Class
actualClass = (targetClass != null ? targetClass : method.getDeclaringClass()); boolean hasIntroductions = hasMatchingIntroductions(config, actualClass); AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance(); for (Advisor advisor : config.getAdvisors()) { if (advisor instanceof PointcutAdvisor) { // Add it conditionally. PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor; if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) { MethodInterceptor[] interceptors = registry.getInterceptors(advisor); MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher(); if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) { 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 { 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)); } } else { Interceptor[] interceptors = registry.getInterceptors(advisor); interceptorList.addAll(Arrays.asList(interceptors)); } } return interceptorList; }

    而config.getAdvisors().length则是ProxyFactoryBean中interceptorNames的配置的长度,我们继续往下看,可以看到这里使用了

       AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();

作为一个注册器,真正的注册器则是这个DefaultAdvisorAdapterRegistry,我们可以看到Spring中使用了很多的涉及模式,把真正的实现和接口分离了开来。

/**	 * Create a new DefaultAdvisorAdapterRegistry, registering well-known adapters.	 */	public DefaultAdvisorAdapterRegistry() {		registerAdvisorAdapter(new MethodBeforeAdviceAdapter());		registerAdvisorAdapter(new AfterReturningAdviceAdapter());		registerAdvisorAdapter(new ThrowsAdviceAdapter());	}@Override	public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {		List
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[interceptors.size()]); }

        我们从名称基本可以看出这里注册了MethodBeforeAdvice、AfterReturningAdvice、ThrowAdvice这三个Advice的适配器,我们来看一个具体的适配器的相关过程

MethodBeforeAdviceAdapter中adapter.getTnterceptor调用的是:

@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的对象。

目前为止,我们返回了所有相关的Interceptor的集合,我们再来看ReflectiveMethodInvocation中的proceed方法:

if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {			// Evaluate dynamic method matcher here: static part will already have			// been evaluated and found to match.			InterceptorAndDynamicMethodMatcher dm =					(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;			if (dm.methodMatcher.matches(this.method, this.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 {			// It's an interceptor, so we just invoke it: The pointcut will have			// been evaluated statically before this object was constructed.			return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);		}

 调用的便是MethodBeforeAdviceInterceptor、AfterReturningAdviceInterceptor、ThrowsAdviceInterceptor这单个Interceptor的相关的invoke方法了,分析这三个invoke方法,我们可以看见,在这里我们实现aop切面中的advice,对方法的前后实现了插入拦截。

    例如:

public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {	private MethodBeforeAdvice advice;	/**	 * Create a new MethodBeforeAdviceInterceptor for the given advice.	 * @param advice the MethodBeforeAdvice to wrap	 */	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();	}}

总结一下:

Spring的Aop归根到底使用的还是jdk的反射。

主要流程是这样的:

    ProxyFactoryBean(interceptorNames对象注入)——>getObject方法(初始化拦截器链)——>getSingletonInstance方法(判断target拦截对象是否为接口,使用不同的代理方式,并将ProxyFactoryBean对象注入相关代理接口)——>JdkDynamicAopProxy和ObjenesisCglibAopProxy接口调用相关的invoke方法和intercep方法作为代理的入口——>最终转化成ReflectiveMethodInvocation的proceed方法——>proceed方法中调用之前获取的拦截器链进行匹配拦截,对代理对象进行Advice切面增强。

 

补充拦截器链的相关过程

       ProxyFactoryBean(interceptorNames对象注入)——>getObject方法——>initializeAdvisorChain——>addAdvisorOnChainCreation()——>AdvisedSupport的addAdvisor()——>DefaultAdvisorChainFactory的getInterceptorsAndDynamicInterceptionAdvice——>DefaultAdvisorAdapterRegistry的getInterceptors进行适配并返回相关拦截器——>调用连接器链的相关拦截器进行拦截

转载于:https://my.oschina.net/guanhe/blog/1476148

你可能感兴趣的文章
Ruby中类 模块 单例方法 总结
查看>>
jQuery的validate插件
查看>>
5-4 8 管道符 作业控制 shell变量 环境变量配置
查看>>
Enumberable
查看>>
开发者论坛一周精粹(第五十四期) 求购备案服务号1枚!
查看>>
validate表单验证及自定义方法
查看>>
javascript 中出现missing ) after argument list的错误
查看>>
使用Swagger2构建强大的RESTful API文档(2)(二十三)
查看>>
Docker容器启动报WARNING: IPv4 forwarding is disabled. Networking will not work
查看>>
(转)第三方支付参与者
查看>>
程序员修炼之道读后感2
查看>>
DWR实现服务器向客户端推送消息
查看>>
js中forEach的用法
查看>>
Docker之功能汇总
查看>>
!!a标签和button按钮只允许点击一次,防止重复提交
查看>>
(轉貼) Eclipse + CDT + MinGW 安裝方法 (C/C++) (gcc) (g++) (OS) (Windows)
查看>>
还原数据库
查看>>
作业调度框架 Quartz.NET 2.0 beta 发布
查看>>
mysql性能的检查和调优方法
查看>>
项目管理中的导向性
查看>>