AOP
Aop:指定程序运行期间,将某段代码动态的切入到指定方法的指定位置
eg:将(日志功能)某段代码动态的切入(不把日志代码写在业务逻辑层)到指定方法(±/*)的指定位置(方法的开始和结束)
步骤:
1.将目标类和切面类(封装了通知方法(在目标方法的执行前后执行的方法))加入到ioc容器中
2.@Aspect–切面类(告诉spring那是是切面类)
3.告诉Spring,切面类里面的方法,都是何时运行的;
@Before(“execution( 访问权限符 返回值类型 全类名.方法(参数))”):在目标方法之前运行—前置通知
@After(“execution( 访问权限符 返回值类型 全类名.方法(参数))”) :在目标方法之后运行—后置通知
@AfterReturning(“execution( 访问权限符 返回值类型 全类名.方法(参数))”):在目标方法正常返回之后运行----异常通知
@AfterThrowing(“execution( 访问权限符 返回值类型 全类名.方法(参数))”):在目标方法抛出异常之后运行—异常通知
@Around:环绕 —环绕通知
Aop细节
1.ioc容器中拿到的是组件的代理对象 $proxy
2.没有接口spring自动创建代理接口
3.(“execution( 访问权限符 返回值类型 全类名.方法(参数))”)
切入点表达式:语法 通配符
*:匹配一个或者多个字符
表达式 | execution(***** com.atguigu.spring.ArithmeticCalculator.*(…)) |
---|---|
含义 | ArithmeticCalculator接口中声明的所有方法。 一个“”代表任意修饰符及任意返回值。 第二个“”代表任意方法。 “…”匹配任意数量、任意类型的参数。 若目标类、接口与该切面类在同一个包中可以省略包名。 |
表达式 | execution(public * ArithmeticCalculator.*(…)) |
---|---|
含义 | ArithmeticCalculator接口的所有公有方法 |
表达式 | execution(public double ArithmeticCalculator.*(…)) |
---|---|
含义 | ArithmeticCalculator接口中返回double类型数值的方法 |
表达式 | execution(public double ArithmeticCalculator.*(…)) | |
---|---|---|
含义 | ArithmeticCalculator接口中返回double类型数值的方法 | |
表达式 | execution(public double ArithmeticCalculator.*(double, …)) | |
含义 | 第一个参数为double类型的方法。“…” 匹配任意数量、任意类型的参数。 |
表达式 | execution(public double ArithmeticCalculator.*(double, double)) |
---|---|
含义 | 参数类型为double,double类型的方法 |
③在AspectJ中,切入点表达式可以通过 “&&”、“||”、“!”等操作符结合起来。
表达式 | execution (* .add(int,…)) || execution( *.sub(int,…)) |
---|---|
含义 | 任意类中第一个参数为int类型的add方法或sub方法 |
通知顺序:
正常执行:@Before === @After===@AfterReturning
异常执行:@Before === @After===@AfterThowable
获取目标方法的详细信息:参数加入JoinPoint:封装了当前目标方法的详细信息
JoinPoint.getArgs()–获取目标方法运行时参数
JoinPoint.getSignature()—获取方法切名
接收异常 通知注解 + throwing(参数名)
接收返回值 通知注解 + returning(参数名)
抽取可重用的切入点表达式
1.随便声明一个没有返回void的空方法
@Pointcut注解将一个切入点声明成简单的方法。切入点的方法体通常是空的,因为将切入点定义与应用程序逻辑混在一起是不合理的。
环绕通知:是优于普通通知执行
[普通前置]
{
环绕前置
try{
目标方法执行
}catch(){}finall
环绕执行,目标方法执行
环绕返回/出现异常
环绕后置
}
[普通后置]
[普通方法返回/方法异常]
执行顺序
环绕前置—普通前置—目标方法执行----环绕正常返回/出现异常—环绕后置—普通后置—普通返回或者异常
实现Ordered接口,getOrder()方法的返回值越小,优先级越高。