Spring实现`aop`过程
对AOP
术语进行解释
1.连接点
类里面哪些方法可以被增强,这些方法称为连接点【如下面Student
类中的study
review
note
方法都可以被增强,所以都可以称为连接点】
public class Student {public void study(){System.out.println("海康学习aop。。。");}public void review(){System.out.println("海康aop。。。");}public void note(){System.out.println("做aop笔记。。。");}
}
2.切入点
实际被真实增强的方法,称为切入点【表示要增强那个方法,例如:增强study
方法,那么study
就是切入点】
3.通知(增强)
(1)实际增强的逻辑部分称为通知(增强)
(2)通知多种类型:
- 前置通知:就是在增强该方法前执行:使用
@Before
注解 - 后置通知:就是在增强该方法后执行:使用
@AfterReturning
注解,如果出现异常则不会该增强方法 - 环绕通知:就是在该方法前后都会执行:
@Around
注解,需要传入ProceedingJoinPoint
类调用proceed()方法表示调用需要增强的方法
- 异常通知:就是该方法出现异常才会执行:
@AfterThrowing
注解 - 最终通知:就是该方法不管是否出现异常都会执行【相当于
try
中的finally
】@After
注解
4.切面
把通知的行为应用到切入点过程中
例如:对`study`方法进行增强,
在`study`执行前先执行`paly方法`,
这一过程就可以理解为切面
AOP
实现准备工作
1.Spring
框架一般都是基于AspectJ
实现AOP
操作
AspectJ
不是Spring
组成部分,独立AOP
框架,一般把AspectJ
和Spring
框架一起使用,进行AOP
操作
2.基于AspectJ
实现AOP
操作有两种方式:
基于
xml
配置文件方式基于注解方式实现方式(推荐)
使用
AspectJ
实现AOP
操作第一步引入jar
包
4.切入点表达式
(1)切入点表达式作用:知道对哪个类里面的哪个方法进行增强
(2)语法结构:execution([权限修饰符][返回类型][类全路径][方法名](参数列表))
返回类型可以不写
举例1:
对com.haikang.dao.UserDao类里面的`add`方法进行增强execution(* com.haikang.dao.UserDao.add(..))举例2:
对com.haikang.dao.UserDao类里面所有方法进行增强execution(* com.haikang.dao.UserDao.*(..) )举例3:
对com.haikang.dao包里面所有有类,类里面所有方法进行增强execution(* com.haikang.*.*(..))
AOP
操作AspectJ
1.创建类,在类里面定义方法
2.创建增强类(编写增强逻辑代码)【需要在该类中 @Aspect
表示是增强类】
3.进行通知的配置
1.在Spring
配置文件中,需要开启两个命名空间context
和aop
2.开启注解扫描
3.使用注解注入被增强类和增强类的对象
4.在增强类上面添加@Aspect
【表示该类为代理类】
5.Spring
配置文件中开启生成代理对象
4.配置不同类型通知
在增强类的里面,在作为通知方法上面添加通知类型注解,使用切入点表达式配置
步骤
1.创建类,在类里面定义方法,并且在IOC
容器中注入该类对象
@Component
public class Student {public void study(){System.out.println("海康学习aop。。。");}public void review(){System.out.println("海康aop。。。");}public void note(){System.out.println("做aop笔记。。。");}
}
2.定义增强类,并且添加@Aspect
注解表示是代理类,同时并在IOC
容器中注入该类对象
@Component
@Aspect
public class StudentProxy {// 表示在执行Study方法先打一小王者荣耀,三个小时@Before("execution(* com.haikang.aop.jdk2.Student.study(..))")public void before(){System.out.println("执行前增强...");System.out.println("表示在执行Study方法先打一小王者荣耀,三个小时");}
}
3.创建bean.xml
文件,引入context
命名空间和aop
命名空间,在配置文件中开启组件扫描和开启自动生成代理对象
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!--开启组件扫描--><context:component-scan base-package="com.haikang.aop.jdk2"/><!--开启生成代理类--><aop:aspectj-autoproxy />
</beans>
test
类
public class AopTest {@Testpublic void testAop(){ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");Student student = context.getBean("student", Student.class);student.study();}
}
前置增强
表示是在执行被增强的方法执行,不管被增强的方法是否出现异常,都会执行
// 表示在执行Study方法先打一小王者荣耀,三个小时@Before("execution(* com.haikang.aop.jdk2.Student.study(..))")public void before(){System.out.println("执行前增强...");System.out.println("表示在执行Study方法先打一小王者荣耀,三个小时");}
环绕增强:
public void review(){System.out.println("海康复习aop两分钟。。。呵呵,够了");}// 表示在执行review方法前面都需要进行增强@Around("execution(* com.haikang.aop.jdk2.Student.review(..))")public void around(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println("在复习`aop前打三个小时王者荣耀......`");joinPoint.proceed();//调用增强方法System.out.println("复习完`aop`刷五个小抖音......");}
注意是:环绕增强,被增强的方法如果出现了异常,只会执行前的增强,没有对被方法执行后进行增强
例如:手动模拟一个算数异常
// 表示在执行review方法前面都需要进行增强@Around("execution(* com.haikang.aop.jdk2.Student.review(..))")public void around(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println("在复习`aop前打三个小时王者荣耀......`");joinPoint.proceed();//调用增强方法System.out.println("复习完`aop`刷五个小抖音......");}public void review(){int i = 10/0;System.out.println("海康复习aop两分钟。。。呵呵,够了");}
后置增强
特点是:后置通知,当被增强的程序出现异常时,则该增强方法则不会被执行
public void note(){System.out.println("海康做aop笔记是认真的。。。");}// 表示后置对`note`增强,表示在被`note`执行后进行增强@AfterReturning("execution(* com.haikang.aop.jdk2.Student.note(..))")public void afterReturning(){System.out.println("对做笔记方法进行后置增强,做笔记我是认真的,哈哈。。。");}
异常通知:表示只有被增强的方法出现异常时,才会执行该增强方法
public void study(){int[] arr = {1,2};arr[5] = 10;//数组下标越界异常System.out.println("海康学习aop。。。");}// 异常通知,表示只有出现了异常该方法才会被执行@AfterThrowing("execution(* com.haikang.aop.jdk2.Student.study(..))")public void throwing(){System.out.println("被增强的方法出现异常了。。。呵呵");}
最终异常:【不管是否出现异常都会执行方法】
public void finallyMethod(){System.out.println("学习。。。");}// 最终通知,不管是否出现异常都会被执行的方法@After("execution(* com.haikang.aop.jdk2.Student.finallyMethod(..))")public void after(){System.out.println("最终还是要好好学习的,不管是否出现异常。。。");}
综合案例
1.定义被增强类
/*** @Author 海康* @Version 1.0*/
@Component
public class Student {public void study(){int[] arr = {1,2};arr[5] = 10;//数组下标越界异常System.out.println("海康学习aop。。。");}public void review(){int i = 10/0;System.out.println("海康复习aop两分钟。。。呵呵,够了");}public void note(){System.out.println("海康做aop笔记是认真的。。。");}public void finallyMethod(){System.out.println("学习。。。");}
}
2.定义增强类
/*** @Author 海康* @Version 1.0*/
@Component
@Aspect
public class StudentProxy {// 表示在执行Study方法先打一小王者荣耀,三个小时
// @Before("execution(* com.haikang.aop.jdk2.Student.study(..))")public void before(){System.out.println("执行前增强...");System.out.println("表示在执行Study方法先打一小王者荣耀,三个小时");}// 表示在执行review方法前面都需要进行增强@Around("execution(* com.haikang.aop.jdk2.Student.review(..))")public void around(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println("在复习`aop前打三个小时王者荣耀......`");joinPoint.proceed();//调用增强方法System.out.println("复习完`aop`刷五个小抖音......");}// 表示后置对`note`增强,表示在被`note`执行后进行增强@AfterReturning("execution(* com.haikang.aop.jdk2.Student.note(..))")public void afterReturning(){System.out.println("对做笔记方法进行后置增强,做笔记我是认真的,哈哈。。。");}// 异常通知,表示只有出现了异常该方法才会被执行@AfterThrowing("execution(* com.haikang.aop.jdk2.Student.study(..))")public void throwing(){System.out.println("被增强的方法出现异常了。。。呵呵");}// 最终通知,不管是否出现异常都会被执行的方法@After("execution(* com.haikang.aop.jdk2.Student.finallyMethod(..))")public void after(){System.out.println("最终还是要好好学习的,不管是否出现异常。。。");}
}
3.定义xml
文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!--开启组件扫描--><context:component-scan base-package="com.haikang.aop.jdk2"/><!--开启生成代理类--><aop:aspectj-autoproxy />
</beans>
4.test类
public class AopTest {@Testpublic void testAop(){ClassPathXmlApplicationContext context =new ClassPathXmlApplicationContext("bean1.xml");Student student = context.getBean("student", Student.class);
// student.study();
// student.review();
// student.note();student.finallyMethod();}
}
细节1:相同的切入点抽取
就是在对同一个切入点进行增强,可以将相同的切入点进行抽取
使用的@Pointcut
注解
@Pointcut(value = "execution(* com.haikang.aopAnno.User.add(..))")
@Component
@Aspect
public class UserProxy {// 抽取相同的切入点@Pointcut(value = "execution(* com.haikang.aopAnno.User.add(..))")public void pointcutDemo(){}// 表示对User中的add方法在执行前进行增强
// @Before("execution(* com.haikang.aopAnno.User.add(..))")@Before("pointcutDemo()")public void before(){System.out.println("before执行前方法前进行增强。。。");}// 表示对User中的add方法在执行后进行增强
// @AfterReturning("execution(* com.haikang.aopAnno.User.add())")@Before("pointcutDemo()")public void afterReturning(){System.out.println("执行方法后进行增强");}// 表示对User中的add方法环绕增强
// @Around("execution(* com.haikang.aopAnno.User.add())")@Before("pointcutDemo()")public void around(ProceedingJoinPoint joinPoint) throws Throwable {// 注意是:add方法出现异常时,只会执行add方法执行前的操作System.out.println("表示对add方法执行前进行增强");// 表示执行add方法joinPoint.proceed();System.out.println("表示对add方法执行后进行增强");}// 表示对User中的add方法最终增强
// @After("execution(* com.haikang.aopAnno.User.add())")@Before("pointcutDemo()")public void after(){System.out.println("表示对add方法进行最终增强,不管是否出现异常都会执行");}// 异常通知【只能该方法出现异常才会被执行】@AfterThrowing("execution(* com.haikang.aopAnno.User.add())")public void afterThrowing(){System.out.println("add方法出现异常了。。。");}
}
细节2:有多个增强类对同一个方法进行增强,设置增强优先级[重点]
在增强类上面添加注解@Order(数字类型值)
,数字类型值越小优先级越高
就是在多个类对一个类中的一个方法都进行增强时,可以设置优先级
@Component
@Aspect
@Order(1)//数值越小优先级越高
public class PersonProxy {// 表示都对User中的add方法在执行前进行增强@Before("execution(* com.haikang.aopAnno.User.add(..))")public void before(){System.out.println("personProxy before执行前方法前进行增强。。。");}
}
@Component
@Aspect
@Order(2)//数值越小优先级越高
public class UserProxy {// 表示对User中的add方法在执行前进行增强@Before("execution(* com.haikang.aopAnno.User.add(..))")public void before(){System.out.println("before执行前方法前进行增强。。。");}}
表示PersonProxy
增强的优先级高于UserProxy
,所以PersonProxy
增强方法先执行
细节3:完全使用注解开发
创建配置类,不需要创建xml
配置文件
注意是:需要添加@EnableAdpectJAutoProxy(proxyTargetClass = true)
注解,表示该类是一个aop
代理类,就是Spring
配置文件中开启生成代理对象作用
@Configuration
@ComponentScan(basePackages = "com.haikang.aopAnno")
@EnableAspectJAutoProxy(proxyTargetClass = true)// 默认是false,需要传入true
public class ConfigProxy {}
test
类
@Testpublic void proxyAnno(){ApplicationContext context =new AnnotationConfigApplicationContext(ConfigProxy.class);// 注意:获取是被增强的类User user = context.getBean("user", User.class);user.add();}
Spring实现`aop`过程相关推荐
- Spring对AOP的支持
Spring对AOP的支持<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" ...
- 动态代理以及对应Spring中AOP源码分析
AOP(面向切面编程)在Spring中是被广泛应用的(例如日志,事务,权限等),而它的基本原理便是动态代理. 我们知道动态代理有两种:基于JDK的动态代理以及基于CGlib动态代理.以下是两种动态代理 ...
- 【SSM框架系列】Spring 的 AOP(面向切面编程)
什么是 AOP AOP 为 Aspect Oriented Programming 的缩写,意思为面向切面编程,是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术. AOP 是 OOP ...
- Spring实现AOP的4种方式
Spring实现AOP的4种方式 先了解AOP的相关术语: 1.通知(Advice): 通知定义了切面是什么以及何时使用.描述了切面要完成的工作和何时需要执行这个工作. 2.连接点(Joinpoint ...
- Spring的AOP原理
AOP是什么? 软件工程有一个基本原则叫做"关注点分离"(Concern Separation),通俗的理解就是不同的问题交给不同的部分去解决,每部分专注于解决自己的问题.这年头互 ...
- spring教程--AOP详解
1 Spring中的AOP 1.1 Spring的传统AOP : AOP:不是由Spring定义.AOP联盟的组织定义. Spring中的通知:(增强代码) 前置通知 org.springframew ...
- Spring教程--AOP简介
AOP的简介 1 什么是AOP AOP Aspect Oriented Programing 面向切面编程 AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码(性能监视.事务管理.安全检查.缓存 ...
- spring之AOP(转)
Spring之AOP篇: AOP框架是Spring的一个重要组成部分.但是Spring IOC 并不依赖于AOP,这就意味着你有权力选择是否使用AOP,AOP作为Spring IOC容器的一个补充,使 ...
- spring的aop的动态代理机制都有哪些_Spring学习(4):Spring AOP
Spring AOP说明 AOP(Aspect Oriented Pragraming)面向切面编程,AOP采用横向抽取机制,取代了传统纵向继承体系的重复性代码(性能监视.事务管理.安全检查.缓存). ...
最新文章
- sklearn 相似度矩阵_精简易懂,30 分钟学会 SVD 矩阵分解,很强!
- Gulp 之图片压缩合并
- 基于DSP的汽车减震弹簧故障诊断仪的设计
- Java中的ThreadPoolExecutor类
- jq-实战之表格筛选
- Linux下压缩包生成与解压命令以及进度
- modern android5.1,Modern摩登印
- 3d游戏编程大师技巧 源代码_C/C++编程入门基础系列:俄罗斯方块小游戏制作,直接源代码分享...
- 数据科学和人工智能技术笔记 八、特征选择
- URLDecoder.decode()转义处理
- 关于STC8H8K64U单片机IAP升级过程
- C64x+ 与 C64x Cache 区别
- python爬取百度图片的思路与代码(最后附上了代码)
- 论文笔记-Suppress and Balance: A Simple Gated Network for Salient Object Detection
- ubuntu机械盘写入cannot be copied because you do not have permissions to create it in the destination.
- 如何编写测试用例?(详细分析)
- 3.Spring Boot使用Apache Curator实现leader选举「第四章 ZooKeeper Curator应用场景实战」「架构之路ZooKeeper理论和实战」
- charles安装及设置(三星手机)
- 2022年大数据开发实习面经总结,已拿顺丰、哔哩哔哩offer
- JAVA代码—算法基础:马走8×8棋盘问题