博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
AOP面向切面编程
阅读量:4486 次
发布时间:2019-06-08

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

1.什么是AOP

AOP 指的是面向切面编程——针对业务过程中的切面(相同代码)进行提取,面对的是处理过程中的某一步骤或阶段

2.AOP作用

AOP 关注点是共同处理,可以通过配置将其作用到某一个或多个目标对象上。好处是实现组件重复利用,改善程序结构,提高灵活性。将共通组件与目标对象解耦。

AOP主要用在处理共通逻辑,如性能统计、日志记录、事务处理、异常处理等,利用AOP可以将这些共通逻辑从普通的业务逻辑代码中分离处理。如果要修改这些逻辑也不会影响普通业务逻辑代码。

3.基本概念及原理

切面(Aspect):封装共通代码的组件,可以作用到其他目标组件的方法上。

目标(target):一个或多个方面所作用的对象

切入点(Pointcut):用于指定哪些组件哪些方法使用切面组件,Spring提供表达式来实现该指定

方法限定表达式:execution(返回值类型 方法名(参数))

通知(Advice):用于指定组件作用到目标组件的具体位置

4.AOP实现原理:基于动态代理技术

5.AOP开发步骤

xml配置方式:

A.创建切面组件类

B.spring配置文件中申明切面组件

C.spring配置文件中使切面组件作用到目标组件的方法上

1     
2
8
9
12
13
14
18
19
20
21
22
23
26
27
28
29

通知类型:

前置通知(before):先执行切面功能再执行目标功能

后置通知(after):先执行目标功能再执行切面功能(无异常情况)

最终通知(after-returning):先执行目标功能再执行切面功能(有无异常都执行切面)

异常通知(after-throwing):先执行目标,捕获抛出异常后执行切面

环绕通知(around):先执行切面前置部分,然后执行目标,最后再执行切面后置部分

切入点表达式:

类匹配: 语法within(包名.类名)

     匹配到具体的类

方法匹配:

    execution(返回值类型  包名.类名.方法名(参数类型,参数类型..))

注解方式实现AOP:

A.xml配置文件中开启组件扫描和注解功能

  <context:component-scan base-package="com.rong.web"/>

  <aop:aspectj-autoproxy proxy-target-class="true"/>

B.目标组件注解

C.切面组件注解

@Component:声明普通、一般组件

@Aspect:声明切面组件

@Before("within(com..UserBizImpl)"):设置前置通知

@AfterReturning("within(com..UserBizImpl)"):设置后置通知

@Around("within(com..UserBizImpl)"):设置环绕通知

@AfterThrowing(pointcut="within(com..UserBizImpl)",throwing="e"):设置异常通知

@After("within(com..UserBizImpl)"):设置最终通知

1 /** 2  * 切面组件类   定义共通的业务逻辑 3  *  4  * @Aspect: 声明当前bean为切面组件bean  5  * @Before(切入点表达式):声明当前方法为前置通知 6  *  7  *  8  * within:按类型匹配 9  * within(包名.类名):给某个具体类的所有方法进行aop切面编程10  * within(包名.*): 给当前包下(不包括子包)下的所有类切面编程11  * within(包名..*):给当前包下(包括子包)下的所有类切面编程12  * 13  * execution:按方法匹配    14  * execution(返回值类型 包名.类名.方法名(参数类型,参数类型,...))15  * execution(* com.rong.web.service..*.find*(..)):16  *  第一个*是表示任意的方法返回值类型   17  *  service..*表示service包和子包下的任意类18  *  find*:表示任意以find开头的方法19  *  (..)表示方法中的参数任意20  * 21  * @author 容杰龙22  */23 //@Aspect24 //@Component//声明组件bean注解
1 public class MyLogger { 2      3     //定义前置通知   在方法执行前执行 4     //@Before("within(com.rong.web.service.*)") 5     public void doBefore(){ 6         System.out.println("日志记录前置操作。。。。。。"); 7     } 8      9     10     @After("within(com..*)")11     //后置通知12     public void doAfter(){13         System.out.println("日志记录后置通知操作。。。。");14     }15     16     /**17      * 18      * 给程序中的所有的find开头的方法添加环绕通知19      * 20      * ProceedingJoinPoint  :  封装了目标组件信息的类21      * @param joinPoint22      */23     24 //    @Around("execution(* com.rong.web.service..*.find*(..))")25     public void doAound(ProceedingJoinPoint joinPoint){26         //getSignature()获取目标方法27         String methodName = joinPoint.getSignature().getName();28         String className = joinPoint.getTarget().getClass().getName();//获取目标组件类名29         30         //环绕通知前置功能31         System.out.println(className+"的"+methodName+"开始执行......");32         long start = System.currentTimeMillis();33         34         try {35             //执行目标组件的方法36             Object proceed = joinPoint.proceed();// 等同于empService.findAll()37         } catch (Throwable e) {38             e.printStackTrace();39         }40         41         //环绕通知后置功能42         System.out.println(className+"的"+methodName+"执行完成......");43         long end = System.currentTimeMillis();44         System.out.println("当前方法总执行时间"+(end-start));45     }46     47     /**48      * service和子包所有类中的方法生效49      * 异常通知调用的切面方法50      * 当发生当前参数类型指定的异常的时候会引发调用,需要注意比当前参数类型大的异常无法引发调用51      * 52      * pointcut:切入点表达式53      * throwing:对应方法中的参数54      */55     @AfterThrowing(pointcut="execution(* com.rong.web.service..*.*(..))",throwing="e")56     public void doException(Exception e){57         System.out.println("异常通知调用。。。。。。。。");58         e.printStackTrace();59     }60     61     /**62      * service包下包括子包的所有方法都执行63      * 返回通知    在执行完目标方法返回之前执行  64      */65     @AfterReturning("execution(* com.rong.web.service..*.*(..))")66     public void doAfterReturning(){67         System.out.println("返回通知执行......");68     }69 }

 

转载于:https://www.cnblogs.com/57rongjielong/p/7801001.html

你可能感兴趣的文章
总结:
查看>>
将文件写到磁盘
查看>>
spring boot 整合redis --sea 方式1
查看>>
Android Http请求方法汇总
查看>>
缓存技术PK:选择Memcached还是Redis?
查看>>
深度工作:充分使用每一份脑力
查看>>
WebService学习笔记系列(四)
查看>>
C# Cache的类方法
查看>>
sql注入式攻击的原理及实例分析 (转载)
查看>>
现代浏览器的工作原理
查看>>
11号团队-团队任务5:项目总结会
查看>>
CPU运行原理
查看>>
UVA529 Addition Chains
查看>>
django项目部署在Apache服务器中,静态文件路径的注意点
查看>>
Unity检查更新
查看>>
转:objective-c 协议和委托
查看>>
day 55 jQuery 之事件 绑定等
查看>>
前端开源项目周报0221
查看>>
Cinder 挂盘创建不成功解决方案日志中报错
查看>>
[CGGeometry]CGRectInset解析
查看>>