个人博客导航页(点击右侧链接即可打开个人博客):大牛带你入门技术栈
基本概念:
AOP: Aspect Oriented Programming,即面向切面编程
指在程序运行期间动态的将某段代码切入到指定方法指定位置进行运行的编程方式
- 前置通知(@Before):在目标方法运行之前执行
- 后置通知(@After):在目标方法运行结束之后执行(无论方法执行成功,还是出现异常,都执行)
- 返回通知(@AfterReturning):在目标方法正常返回之后执行
- 异常通知(@AfterThrowing):在目标方法出现异常后执行
- 环绕通知(@Around):动态代理,手动推进目标方法运行(joinPoint.procced())
返回通知和异常通知只能同时执行一个
基本使用:
-
导入aop依赖:Spring AOP(spring-aspects)
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>5.0.2.RELEASE</version> </dependency>
-
定义一个业务逻辑类
public class MathCalculator { public int div(int a, int b){ return a / b; } }
-
定义一个日志切面类,告诉 Spring 这个类是切面类(在切面类加上:@Aspect),并且,给目标方法标注**“何时何地”**执行(通知注解)
-
切入点基本格式:权限修饰符 方法返回值 全方法名(参数列表类型) 异常类型,加粗的是必填项
-
在@Before注解上引用,如果引用类外的切入点表达式,需要使用全方法名
@Aspect public class LogAspects { //抽取公共的切入点表达式 @Pointcut("execution(* com.spring.aop.MathCalculator.*(..))") public void pointCut(){ } @Before("pointCut()") public void logStart() { System.out.println("方法运行"); } @After("pointCut()") public void logEnd() { System.out.println("方法结束"); } @AfterReturning("pointCut()") public void logReturn() { System.out.println("方法正常返回"); } @AfterThrowing("pointCut()") public void logException() { System.out.println("方法出现异常"); } }
-
-
将切面类和业务逻辑类(目标方法所在类)都注册到ioc容器中,注册的几种方式可以参考前面的博客Spring注解 - 组件的注册
@Bean public MathCalculator mathCalculator(){ return new MathCalculator(); } @Bean public LogAspects logAspects(){ return new LogAspects(); }
-
开启基于注解的AOP模式(在配置类加上:@EnableAspectJAutoProxy)
@Configuration @EnableAspectJAutoProxy public class SpringConfiguration
-
测试一把
@Test public void test1(){ ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfiguration6.class); MathCalculator mathCalculator = (MathCalculator) applicationContext.getBean("mathCalculator"); mathCalculator.div(2, 1); }
运行结果:
-----正常运行----- 方法运行 方法结束 方法正常返回 -------异常------ 方法运行 方法结束 方法出现异常
但上述输出的内容太简单了,如果想要得到方法具体信息怎么办?我们对切面类做一些改造
@Aspect public class LogAspects { @Pointcut("execution(* com.spring.aop.MathCalculator.*(..))") public void pointCut() { } @Before(value = "pointCut()") public void logStart(JoinPoint joinPoint) { //参数列表 Object[] args = joinPoint.getArgs(); //方法名 String methodName = joinPoint.getSignature().getName(); System.out.println(methodName + "方法运行,参数列表:" + Arrays.toString(args)); } @After("pointCut()") public void logEnd(JoinPoint joinPoint) { String methodName = joinPoint.getSignature().getName(); System.out.println(methodName + "方法结束"); } @AfterReturning(value = "pointCut()", returning = "returnInfo") public void logReturn(JoinPoint joinPoint, Object returnInfo) { String methodName = joinPoint.getSignature().getName(); System.out.println(methodName + "方法正常返回,返回值:" + returnInfo); } @AfterThrowing(value = "pointCut()", throwing = "exception") public void logException(JoinPoint joinPoint, Exception exception) { String methodName = joinPoint.getSignature().getName(); System.out.println(methodName + "方法出现异常,异常信息:" + exception); } }
运行结果:
-----正常运行----- div方法运行,参数列表:[2, 1] div方法结束 div方法正常返回,返回值:2 -------异常------ div方法运行,参数列表:[2, 0] div方法结束 div方法出现异常,异常信息:java.lang.ArithmeticException: / by zero
注意:参数
joinPoint
一定要放在参数表的第一位
附Java/C/C++/机器学习/算法与数据结构/前端/安卓/Python/程序员必读/书籍书单大全:
(点击右侧 即可打开个人博客内有干货):技术干货小栈
=====>>①【Java大牛带你入门到进阶之路】<<====
=====>>②【算法数据结构+acm大牛带你入门到进阶之路】<<===
=====>>③【数据库大牛带你入门到进阶之路】<<=====
=====>>④【Web前端大牛带你入门到进阶之路】<<====
=====>>⑤【机器学习和python大牛带你入门到进阶之路】<<====
=====>>⑥【架构师大牛带你入门到进阶之路】<<=====
=====>>⑦【C++大牛带你入门到进阶之路】<<====
=====>>⑧【ios大牛带你入门到进阶之路】<<====
=====>>⑨【Web安全大牛带你入门到进阶之路】<<=====
=====>>⑩【Linux和操作系统大牛带你入门到进阶之路】<<=====天下没有不劳而获的果实,望各位年轻的朋友,想学技术的朋友,在决心扎入技术道路的路上披荆斩棘,把书弄懂了,再去敲代码,把原理弄懂了,再去实践,将会带给你的人生,你的工作,你的未来一个美梦。