SpringBoot(五):aop

来源:互联网 发布:sql触发器类型 编辑:程序博客网 时间:2024/05/17 08:29

一.AOP简介:

面向切面编程,在不改变原有方法的定义与使用、也不改变原程序流程的情况下,可以改变原有方法的功能(如增加一些附加的功能,在指定的地方添加其他函数方法)

特性:

1.解决代码重复性问题

2.实现关注点分离(分离功能性需求和非功能性需求)

优点:

1.集中处理某一关注点/横切逻辑

2.可以很方便的添加/删除关注点

3.侵入性少,增加代码可读性和可维护性

缺点:

性能略低,仅适用于方法调用,必须在Spring容器

应用场景:

1.权限控制

2.缓存控制

3.事务控制

4.审计日志

5.性能监控

6.异常处理.....


二.项目引入springboot-aop依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency>


@Aspect  声明一个切面

@Component   向spring中注入该切面

@Pointcut:声明一个切入点,切入点决定了连接点关注的内容,使得我们可以控制通知什么时候执行。

Spring AOP只支持Spring bean的方法执行连接点。所以你可以把切入点看做是Spring bean上方法执行的匹配。

一个切入点声明有两个部分:一个包含名字和任意参数的签名,还有一个切入点表达式,该表达式决定了我们关注那个方法的执行。

注:作为切入点签名的方法必须返回void 类型


三.Spring AOP支持在切入点表达式中使用如下的切入点指示符:    

within - within(com.example.demo.controller.MyController)   直接指定类路径,或者使用通配符within(com.example..*)
this - this(com.example.demo.service.MyServiceImpl)  拦截这个类的所有方法

target - target(com.example.demo.service.MyService)  拦截实现类的所有方法

bean-bean(*Service),匹配所有以service结尾的bean的所有方法

args - args(Long) 匹配只有一个参数Long的方法,匹配多个参数args(Long,..),这里是以Long开头的参数,不能单独使用,不然会报错.

execution - 格式

execution (modifier-pattern?   //修饰匹配符ret-type-pattern//返回值匹配declaring-type-pattern?//类路径匹配name-pattern(param-pattern)//方法名(参数)匹配throws-pattern?    //异常类型)   ?表示可选项

代码:

@Pointcut("execution(public * com.example.demo.controller.MyController.*(..)))")
参数不写就是拦截无参


@target - @target(xxx)对标记有xxx注解的类做代理

@args - 拦截参数上的注解@args(注解类路径)

@within - 拦截类级别上的注解@within(注解类路径)

/** * @Retention(RetentionPolicy.RUNTIME)注解表明 MyAuth注解将会由虚拟机保留, * 以便它可以在运行时通过反射读取. * @Documented,则它会被 javadoc 之类的工具处理, 所以注解类型信息也会被包括在生成的文档中 * @Target,定义注解的作用目标 * @Inherited,允许子类集成父类的注解 * @author majie * */@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)@Inherited   @Documentedpublic @interface MyAuth {}

@annotation - 拦截方法级别的注解@annotation(注解类路径)

@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)public @interface MyAuth {}

四.五中Advice注解

1.@Before,前置通知

@Before("test() && args(a)")public void before(Long a) {System.out.println("这里可以进行参数验证:"+a);}

2.@After(finally),后置通知,方法执行完成之后

3.@AfterRetruning,返回通知,成功执行以后

@AfterReturning(pointcut = "log()",returning = "object")public void afterRetruning(Object object) {System.out.println("返回值为:" + object);}

4.@AfterThrowing,异常通知,异常抛出以后

5.@Around,环绕通知

@Around("test()")public Object around(ProceedingJoinPoint point) {System.out.println("----before");Object result = null;try {result = point.proceed(point.getArgs());System.out.println("----afterretruning");} catch (Throwable e) {e.printStackTrace();System.out.println("----ex");}finally {System.out.println("----finally");}return result;}
结果:

----before这是一个测试方法----afterretruning----finally