夜光带你走进SSM框架 (四)新的领域

版权声明:Genius https://blog.csdn.net/weixin_41987706/article/details/88871518

夜光序言:

人们总是喜欢找各种借口去逃避现实。

骗着别人,也骗着自己。

没有对错,只问心安。

 

 

 

正文:2.4ReflectiveMethodInvocation. proceed

public Object proceed() throws Throwable {
// 开始执行代理方法。包含通知方法和目标对象中的真实方法。
// 判断当前代理是否还有需要执行通知。如果没有通知,执行目标代码。
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);
}
}

2.5AOP 源码流程图

3 AOP  中常用的 Pointcut-expression


AOP 开发中,有非常重要的几个概念,其中有一个概念叫“切点”。代表通知切入到代码执行流程的那个位置点。

切点一般通过表达式定义。spring 框架会通过 SpringEL 来解析表达式。表达式有多种定义方式。分别对应不同的解析结果。


3.1execution  表达式

语法格式: execution(返回类型 包名.类名.方法名(参数表))
如:
execution(java.lang.String com.xxx.service.AService.test(java.lang.Integer))
在类型 com.xxx.service.AService 中有方法 test,且参数为 Integer,返回类型为 String 时增加切面。
execution(* com.xxx.AService.*(..))
com.xxx.AService 类型中的任意方法,任意类型返回结果,参数表不限定,都增加切面。
应用: 最常用 。也是相对最通用。根据方法执行的标准,定义切点。如:事务处理,日志处理。

3.2target  表达式


以目标对象作为切点的表达式定义方式。
语法: target(包名.接口名)
如: target(com.xxx.IA) - 所有实现了 IA 接口的实现类,作为代理的目标对象,会自动增加通知的织入,实现切面。

应用:为某一个具体的接口实现提供的配置。如:登录。登录的时候需要执行的附属逻辑是比较多的。在不同的业务流程中,附属逻辑也不同。如:电商中,可能在登录的时候,需要去执行购物车合并。

3.3this  表达式


实现了某接口的代理对象,会作为切点。 和 target 很类似。

语法: this(包名.接口名)
如: this(com.xxx.IA) - 代理对象 Proxy 如果实现了 IA 接口,则作为连接点。
应用:针对某个具体的代理提供的配置。比 target 切点粒度细致。因为目标对象可以多实现。代理对象可以针对目标对象实现的多个接口的某一个接口,提供特定的切点。如:银行中的登录,银行中的帐户种类非常多。且有交叉。如:借记卡,贷记卡,借记还贷卡,贷记还贷卡等。可以针对还贷接口提供一个切点,做还贷信息的记录等。


3.4within  表达式


以包作为目标,定义切点。
语法: within(包名.*) - 代表在包中的任意接口或类型都作为切点。

应用: 针对某一个包提供的切点,粒度比 target 粗糙。如:某包中的所有接口都需要执行某附属逻辑。如:电商平台中的下订单。下订单服务中可能需要特定的逻辑(时间戳校验,库存检查等),这些逻辑,是其他业务线中不需要提供切面的。


3.5args  表达式


以参数标准作为目标,定义切点。

语法: args(类型,类型) - 代表方法的参数表符合要求的时候,作为切点。参数表是有顺序的。
应用:主要应用在参数校验中。如:登录的时候必须传递两个字符串参数(登录名和密码)。可以使用 args 来限定。 配合这 execution 实现。 如: execution( * xxxx.*.login(..) )args(string,string)。 是使用频率最低的表达式 

猜你喜欢

转载自blog.csdn.net/weixin_41987706/article/details/88871518
今日推荐