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

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

AOP相关术语:

Joinpoint (连接点):所谓连接点是指那些被拦截到的点,在spring中,这些点指的是方法,因为spring 只支持方法类型的连接点。

Pointcut(切入点):所谓切入点是指我们要对那些Joinpoint进行拦截的定义。

Adevice(通知/增强):所谓通知是指拦截到Joinpoint之后要做的事,分为前置通知,后置通知,异常通知,最终通知,环绕通知(切面要完成的功能)

Introduction(引介):引介是一种特殊的通知在不修改类代码的前提下,Introduction可以在运行期为类动态的添加一些方法或Field

Target(目标对象):代理的目标对象

Weaving(织入):是指把增强应用到目标对象来创建新的代理对象的过程。spring 采用动态代理织入,而AspectJ采用编译器织入和类装载期织入

Proxy(代理):一个类被AOP织入增强后,就产生一个结果代理类

Aspect(切面):是切入点和通知(引介)的结合

通知类型:

  • 前置通知:在目标方法执行前执行
  • 后置通知:在目标方法执行后执行
  • 环绕通知:在目标方法执行前和执行后通知
  • 异常抛出通知:在目标方法出现异常时执行
  • 最终通知:无论目标方法是否出现异常,最终通知都会执行

引入AOP约束:

 

第一种方式我们可以在Xml文件中进行配置:

编写目标对象:

public interface PersonDao {     public String savePerson();}

 

1 public class PersonDaoImpl implements PersonDao {2     @Override3     public String savePerson() {4         System.out.println("save person");5         return "return SavePerson";6     }7 }

 

 

编写切面类 进行事务管理:

1 package com.person; 2  3 import javax.persistence.criteria.Join; 4  5 import org.aspectj.lang.JoinPoint; 6 import org.aspectj.lang.ProceedingJoinPoint; 7  8 public class Transaction { 9 /**10  * 前置通知11  *  JoinPoint 12  *      连接点,代表一个方法,客户端调用哪个方法那个方法就是连接点13  *  通过该参数,可以获取到连接点的一些信息14  * @param joinPoint15  */16     public void beginTransaction(JoinPoint joinPoint){17         //获取目标类18         System.out.println("targetClass   " + joinPoint.getTarget());19         //获取连接点的参数20         System.out.println("args  " + joinPoint.getArgs());21         //获取连接点的名称22         System.out.println("methodName  " + joinPoint.getSignature().getName());23         System.out.println("开启事务");24     }25     /**26      * 后置通知  方法遇到异常  不执行27      * JoinPoint 连接点28      * Object val 接受目标方法的返回值 与配置文件中参函数名一致29      * @param joinPoint30      */31 public void commit(JoinPoint joinPoint,Object val){32     System.out.println(val);33     System.out.println("事务提交");34     35 }36 /**37  * 最终通知  无论是否发生异常都会执行38  * @param joinPoint39  */40 public void finalyMethod(JoinPoint joinPoint){41     System.out.println("finally method");42 } 43 /**44  * 异常通知45  * @param joinPoint    连接点46  * @param ex     接收异常   在文件中配置 参数名一致47  */48 public void throwingMethod(JoinPoint joinPoint,Throwable ex) {49     System.out.println(ex.getMessage());    50 }51 /**52  *  环绕通知  在方法前后执行 能够控制方法是否执行53  *      其主要在于,54  *      如果使用around 来作为切入面,连接点的方法就嵌套在around中来执行,55  *      如果around中不获取连接点来执行方法,那么原本的方法不会执行56  *  57  *      如果在around执行时同样使用了aftereturning来拦截return就必须,58  *      在around中执行方法的哪一行就行return的获取,再由around再次进行return,59  *      否则afterreturning是拦截不到return的,因为return在around已经断掉了60  *  61  *  注意在around 中使用的是 ProceedingJoinPoint62  * @param joinPoint63  * @throws Throwable64  */65 public Object aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable{66     System.out.println("aaaaaa");67     Object val = joinPoint.proceed();//执行目标方法68     System.out.println("bbbbbb");69     return val;70 }71 //public void aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable{72 //    System.out.println("aaaaaa");73     Object val = joinPoint.proceed();//执行目标方法74 //    System.out.println("bbbbbb");75     return val;76 //}77 }

 

修改Xml配置文件进行注册:

 

1 
2
7
8
9
10
13
14
15
16
17
19
20
21
22
23
24
25
26
27
28 29

 

 

 

 

测试代码:

 

1 import org.springframework.context.ApplicationContext; 2 import org.springframework.context.support.ClassPathXmlApplicationContext; 3  4 public class PersonTest { 5  6     public static void main(String[] args) { 7         ApplicationContext context = new ClassPathXmlApplicationContext("person.xml"); 8         PersonDao personDao = (PersonDao) context.getBean("personDao"); 9         10         personDao.savePerson();11     }12 }

 

 

 输出结果如下:

targetClass   com.person.PersonDaoImpl@713055ba args  [Ljava.lang.Object;@20a07db0 methodName  savePerson 开启事务 save person return SavePerson 事务提交 finally method

 第二种方式我们可以利用注解来配置

编写目标对象:

1 public class Book { 2  3     public String add() { 4         System.out.println("add....books....."); 5         return "return Save"; 6     } 7     public void query() { 8         System.out.println("query.........");         9     }10     public void delete () {11         System.out.println("delete....books.....");12         13     }14 }

 

编写切面类:

1 import org.aspectj.lang.JoinPoint; 2 import org.aspectj.lang.ProceedingJoinPoint; 3 import org.aspectj.lang.annotation.After; 4 import org.aspectj.lang.annotation.AfterReturning; 5 import org.aspectj.lang.annotation.AfterThrowing; 6 import org.aspectj.lang.annotation.Around; 7 import org.aspectj.lang.annotation.Aspect; 8 import org.aspectj.lang.annotation.Before; 9 //声明切入面10 @Aspect11 public class BookAspect {12 13     //在方法上面使用注解完成增强配置14     @Before(value="execution(* cn.aop.Book.*(..))")15     public void before(JoinPoint joinPoint) {16         //获取目标类 17         System.out.println("target :" + joinPoint.getTarget());18         //获取连接点的参数19         System.out.println("args  :" + joinPoint.getArgs());20         //获取链接点的名称21         System.out.println("methodName  :" + joinPoint.getSignature().getName());22         System.out.println("before..............");23     }24     25     @After(value="execution(* cn.aop.Book.*(..))" )    26     public void after() {27         System.out.println("after..............");28     }29 //    @AfterReturning(pointcut="pointcut1",returning="val")30 //    @AfterReturning(value="execution(* cn.aop.Book.*(..))",returning="val")31     public void afterReturning(Object val){32         System.out.println(val);33         System.out.println("afterReturning....");34         35     }36     @AfterThrowing(value = "execution(* cn.aop.Book.*(..))")37     public void afterThrowing(){38         System.out.println("afterThrowing.....");39         40     }41     @Around(value="execution(* cn.aop.Book.*(..))")42     public Object around(ProceedingJoinPoint joinPoint) throws Throwable{43         System.out.println("aaaaaa");44         Object val = joinPoint.proceed();45         System.out.println("bbbbbb");    46         return val;47     }48     49 }

Xml文件稍作修改:

1 
2
7 8
9
10
11
12
13 14
17

 

编写测试类:

1 import javax.sound.midi.Soundbank; 2 import org.springframework.beans.BeansException; 3 import org.springframework.context.ApplicationContext; 4 import org.springframework.context.support.ClassPathXmlApplicationContext; 5  6 public class TestBook { 7  8     public void testDemo(){ 9             ApplicationContext context = 10                     new ClassPathXmlApplicationContext("book.xml");11             Book book = (Book) context.getBean("book");12             book.add();13             System.out.print("\n");14                 book.delete();    15 //        System.out.println("\n");16 //        System.out.println(book.query());17         }18     public static void main(String[] args)  {19         TestBook  test = new TestBook();            20                 test.testDemo();21     }22 }

 

测试结果:

aaaaaatarget :cn.aop.Book@61fc0ce6args  :[Ljava.lang.Object;@55a19181methodName  :addbefore..............add....books.....bbbbbbafter..............aaaaaatarget :cn.aop.Book@61fc0ce6args  :[Ljava.lang.Object;@1b6cdb87methodName  :deletebefore..............delete....books.....bbbbbbafter..............

 

转载于:https://www.cnblogs.com/the-wang/p/7663272.html

你可能感兴趣的文章
奇异值分解
查看>>
快速傅里叶变换模块(fft)
查看>>
随机数模块(random)
查看>>
杂项功能(排序/插值/图像/金融相关)
查看>>
pandas核心
查看>>
线性回归
查看>>
机器学习学习索引
查看>>
多项式回归
查看>>
Python-字符串
查看>>
MySQL8.0安装以及介绍(二进制)
查看>>
MySQL权限系统
查看>>
Python-集合
查看>>
转:标签中的href如何调用js
查看>>
CrawlSpiders简介
查看>>
面向对象编程
查看>>
django-rest-framework 视图的使用规则 总结分享
查看>>
drf 访问文档出现错误'AutoSchema' object has no attribute 'get_link'
查看>>
django-rest-framwork 错误信息整理
查看>>
第一讲 评估类模型之层次分析法
查看>>
评估类模型之优劣解距离法Topsis模型
查看>>