AOP和spring AOP学习纪录

AOP基本观点的明白

面向切面AOP主要是在编译期或运行时,对程序举行织入,实现署理,

对原代码毫无侵入性,不损坏主要营业逻辑,削减程序的耦合度。

  • 主要应用局限:
    日志纪录,性能统计,平安控制,事务处置,异常处置等等

名词性观点

  • 切面(Aspect)
    通常是一个类,在里面可以界说切入点和通知,即切面=切入点+通知
  • 连接点(Joint Point)
    被阻挡到的点,由于 Spring 只支持方式类型的连接点,以是在 Spring 中连接点指的就是被阻挡的到的方式,实际上连接点还可以是字段或者组织器。
  • 切入点(Pointcut)
    对连接点举行阻挡的界说。
  • 通知(Advice)
    阻挡到连接点之后所要执行的代码,通知分为前置、后置、异常、最终、围绕通知五类。
  • AOP 署理
    AOP 框架建立的工具,署理就是目的工具的增强。Spring 中的 AOP 署理可以使 JDK 动态署理,也可以是 CGLIB 署理,前者基于接口,后者基于子类。
  • 织入(Weaving)
    把切面加入到工具,并建立出署理工具的历程。

动态署理

在运行时代天生工具举行署理,

spring AOP就是动态署理。

静态署理

自己编写署理工具,在编译器织入,

AspectJ就是在编译时代举行织入,从而削减对运行时效率的影响。

SpringAOP

凭据工具是否是实现类选择署理的方式

  • 若是要署理的工具实现了接口,spring AOP会凭据接口,使用JDK Proxy建立署理

  • 若是没有实现接口,则通过CGLIB署理

固然也可以指定都使用CGLIB举行切入,而JDK方式不适用于没有接口实现的目的类

对于JDK proxy

Jdk proxy会实现目的类的接口,署理逻辑就在新的实现类中

只能对实现类举行署理,性能也优于CGLIB,以是平时都是分为”接口-实现iml”来设计。

对于CGLIB

cglib会建立一个署理目的类的子类,而署理逻辑就在这一子类中添加,

然后获得这一子类的工具,也就是署理增强后的工具,一切都是动态的,

详细实现有待学习。

切面类

使用@Aspect注解界说切面类

好比这样

@Component
@Aspect
@Oder(99)
public class WebLogAspect {}

另外对同一个方式有多个切面举行署理的时刻,难免需要区分执行顺序,

这时刻可以使用@Order注解界说优先级,数字越低,级别越高。

切面Advice

执行顺序around -> before -> around -> after -> afterRuternning

@After

第一个参数都必须是JoinPoint类型

在目的方式完成后通知,

无论方式是以何种方式完成,异常也是云云

@After-returning

第一个参数都必须是JoinPoint类型

竣事并平安返回时通知,异常不通知

@After-throwing

第一个参数都必须是JoinPoint类型

异常时通知

@Before

第一个参数都必须是JoinPoint类型

顾名思义

@Around

最壮大的通知

进阶之路 | 巧妙的Thread之旅

第一个形参必须是ProceedingJoinPoint类型,

public interface ProceedingJoinPoint extends JoinPoint {
    void set$AroundClosure(AroundClosure var1);

    default void stack$AroundClosure(AroundClosure arc) {
        throw new UnsupportedOperationException();
    }

    Object proceed() throws Throwable;

    Object proceed(Object[] var1) throws Throwable;
}

可以看到它继续自JoinPoint,多了proceed方式

注解的方式体内挪用ProceedingJoinPoint参数的proceed()方式才会执行目的。

挪用这个方式时,还可以传入一个Object[]工具作为参数

可以通过这个切面决议方式是否执行,改变传入参数,改变返回值,检查异常等

参数方式

  • getArgs(): Returns the method arguments.

  • getThis(): Returns the proxy object.

  • getTarget(): Returns the target object.

  • getSignature(): Returns a description of the method that is being advised.

  • toString(): Prints a useful description of the method being advised.

切点表达式

有关切点表达式,建议阅读 传送门

可以界说一个切点,之后就不用逐一指定,直接带入value即可,例如:

@Pointcut("execution(* com.hyg.app.controller..*.*(..))")
public void webLog(){}

@Before(value = "webLog()")
public void doBefore (JoinPoint jp){
  String name = jp.getSignature().getName();
  System.out.println(name+"最先执行");
}

execution

表达式中最常用的方式是execution,粒度最小

对于execution(* com.hyg.app.controller..*.*(..))

  • execution表达式的类型指定
  • 第一个*代表 随便的返回值类型
  • com.jiuxian aop所切的包名
  • 包后面..示意当前包其子包,一个.是当前包,两个.就包罗所有子包
  • 第二个* 示意类名,代表所有类
  • .*(..)示意任何方式, 括号代表参数 .. 示意随便参数

后面那串器械,可以记为每一个.都是更深的一个粒度

来个正确点的示例:

execution(* com.hyg.app.service.*Service.add*(String))

示意所有类型的,com.hyg.app.service包下的,

所有以Service末端的类,

add开头的,参数类型为String的方式

例子

在官方文档中有许多示例,如下

所有public方式
execution(public * *(..))

所有名字以set开头的方式
execution(* set*(..))

所有AccountService中实现的接口的方式
execution(* com.xyz.service.AccountService.*(..))

所有service包下的方式
execution(* com.xyz.service.*.*(..))

所有在service包以及子包下的方式
execution(* com.xyz.service..*.*(..))

within(com.xyz.service.*)  所有service包下方式
within(com.xyz.service..*) 所有service包和子包下方式
this(com.xyz.service.AccountService) 匹配accountservice署理的工具
target(com.xyz.service.AccountService) 实现了AccountService接口的工具

拥有transactional注解的
@annotation(org.springframework.transaction.annotation.Transactional)
通报的参数是Serializable的
args(java.io.Serializable):

关于execution和within的区别

execution可以指定方式返回类型,类名,方式名和参数名等与方式相关的部件,

而within的最小粒度是类。

关于this和target的区别

this匹配的是署理类,即目的工具被署理后的署理工具

target则是匹配通俗的目的工具

以下情形外,二者的效果都是一致的。

this(SomeObject)或target(SomeObject),这里SomeObject实现了某个接口:对于这种情形,虽然表达式中指定的是一种详细的工具类型,但由于其实现了某个接口,因而Spring默认会使用Jdk署理为其天生署理工具,Jdk署理天生的署理工具与目的工具实现的是同一个接口,但署理工具与目的工具照样差别的工具,由于署理工具不是SomeObject类型的,因而此时是不相符this语义的,而由于目的工具就是SomeObject类型,因而target语义是相符的,此时this和target的效果就产生了区别;这里若是强制Spring使用Cglib署理,因而天生的署理工具都是SomeObject子类的工具,其是SomeObject类型的,因而this和target的语义都相符,其效果就是一致的。

args

用于指定参数类型,类型必须是全路径的

官网注释

  • execution: For matching method execution join points. This is the primary pointcut designator to use when working with Spring AOP.
  • within: Limits matching to join points within certain types (the execution of a method declared within a matching type when using Spring AOP).
  • this: Limits matching to join points (the execution of methods when using Spring AOP) where the bean reference (Spring AOP proxy) is an instance of the given type.
  • target: Limits matching to join points (the execution of methods when using Spring AOP) where the target object (application object being proxied) is an instance of the given type.
  • args: Limits matching to join points (the execution of methods when using Spring AOP) where the arguments are instances of the given types.
  • @target: Limits matching to join points (the execution of methods when using Spring AOP) where the class of the executing object has an annotation of the given type.
  • @args: Limits matching to join points (the execution of methods when using Spring AOP) where the runtime type of the actual arguments passed have annotations of the given types.
  • @within: Limits matching to join points within types that have the given annotation (the execution of methods declared in types with the given annotation when using Spring AOP).
  • @annotation: Limits matching to join points where the subject of the join point (the method being executed in Spring AOP) has the given annotation.

—官方文档—

我的博客:https://www.seyana.life/post/12

原创文章,作者:dddof新闻网,如若转载,请注明出处:https://www.dddof.com/archives/157.html