实习笔记—— AOP开发II(AOP中Advice的类型)
系列文章目录
实习笔记 —— Spring基础
实习笔记 —— IOC反转控制(xml配置文件 + 注解)
实习笔记 —— AOP开发I
文章目录
- 系列文章目录
- 一、AOP中Advice的类型的XML配置文件形式
- 二、AOP中Advice的类型的基本注解形式
- 三、AOP中Advice的类型的切入点注解形式
- 四、总结
一、AOP中Advice的类型的XML配置文件形式
先回顾昨天学的AOP中的相关术语,体会Advice的含义:
实习时介绍了AOP中Advice的五种类型,我们将这五种类型综合起来学习。
1.before advice前置通知: 在执行切点前的通知,可以判断是否可以执行该切点。
2.after-returning advice后置通知: 在运行完切点完未返回之前,进行通知。
3.around advice环绕通知: 包裹一个方法的执行,这是一个功能强大的通知方式。可以在方法执行前或者执行后around advice,也可以用来判断是否往下执行当前的切点,或者返回切点的值。或者抛出一个异常。
4.after throwing advice异常通知: 在运行完切点时抛出异常进行的通知。
5.After advice最终通知:执行完该切点后,进行的通知。
以具体项目为例:(创建项目第一步先导包)
①声明接口:
②声明接口的实现类:
③创建切面类,将所有新添加的需求对应的方法写在这里:
package com.high.demo1;import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;//最开始导错包了import org.aopalliance.intercept.Joinpoint;// 切面类,存放用户要增加的方法
public class MyAspectXML {// Advice:通知,增强;甲方要求新增加的方法或需求(如显示用户身份需求)
// public void checkPri() {// System.out.println("进行身份验证........");
// } // ctrl + alt + down// 1.前置通知public void checkPri(JoinPoint jointJoinpoint) {System.out.println("save方法的前置通知:进行身份验证........" + jointJoinpoint);}// 2.后置通知public void writeLog(Object result) {System.out.println("delete方法的后置通知:Be recorded....." + result);}// 3.环绕通知:性能监控// ProceedingJoinPoint是指被增加的接入点find()public Object aroundOne(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println("环绕通知前.....");// 调用了此方法对应的切入点 find()方法,基本都要写,用于体现“环绕”Object proceed = joinPoint.proceed(); System.out.println("环绕通知后前.....");return proceed;}// 4.异常抛出通知// 参数: Throwablepublic void afterThrow(Throwable ex) {System.out.println("Error appeared." + ex.getMessage());}// 5.最终通知 —— 相当于异常中的 finally代码块public void afterLast() {System.out.println("This is the final Advice.");}
}
④编写XML配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><!-- 把ProductDaoImpl类交给spring管理 --><!-- 创建目标类 target --><bean name="productDao" class="com.high.demo1.ProductDaoImpl"></bean> <!-- 将切面类交给spring管理 --><bean name="myAspect" class="com.high.demo1.MyAspectXML"></bean> <!-- 通过AOP配置来完成对目标的代理 --><!-- MyAspectXML类中的checkPri作用于切入点pointcut1上 --><aop:config><!-- 声明第一个切入点,id值全局唯一 --> <aop:pointcut id="pointcut1" expression="execution(* com.high.demo1.ProductDaoImpl.save(..))"/><aop:pointcut id="pointcut2" expression="execution(* com.high.demo1.ProductDaoImpl.delete(..))"/><aop:pointcut id="pointcut3" expression="execution(* com.high.demo1.ProductDaoImpl.find(..))"/><aop:pointcut id="pointcut4" expression="execution(* com.high.demo1.ProductDaoImpl.update(..))"/><aop:pointcut id="pointcut5" expression="execution(* com.high.demo1.ProductDaoImpl.find(..))"/><!-- 引入切面类MyAspect --><aop:aspect ref="myAspect"><!-- 完成织入过程,切面类作用在谁身上(只写方法名),以及切入点 --><!-- 通知的类型:1.前置通知 before --><aop:before method="checkPri" pointcut-ref="pointcut1"/><!-- 2.后置通知 after-returning --><aop:after-returning method="writeLog" pointcut-ref="pointcut2" returning="result"/><!-- 3.环绕通知 --><aop:around method="aroundOne" pointcut-ref="pointcut3"/><!-- 4.异常通知 --><aop:after-throwing method="afterThrow" pointcut-ref="pointcut4" throwing="ex"/><!-- 5.最终通知 --><aop:after method="afterLast" pointcut-ref="pointcut5"/></aop:aspect></aop:config>
</beans>
⑤编写测试类:
package com.high.demo1;import javax.annotation.Resource;import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;// AOP入门
// 书写类注解,类层级,所以写在类外面
// 整合JUnit4
@RunWith(SpringJUnit4ClassRunner.class)
// 加载XML配置文件(严格按照格式书写,不要添加任何空格等字符)
@ContextConfiguration("classpath:applicationContext.xml")public class SpringDemo {// 1.未使用注解整合JUnit
// @Test
// public void demo() {// ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
// ProductDaoImpl product = (ProductDaoImpl)applicationContext.getBean("productDao");
//
// product.save();
// product.update();
// product.delete();
// product.find();
// }// 2.整合后// 想用哪个类就注入哪个类,交给spring管理// 对私有属性的引入@Resource(name = "productDao")private ProductDao productDao;@Testpublic void demo2() {productDao.save();productDao.update();productDao.delete();productDao.find();}
}
在正常无Advice的情况下,测试类的输出结果为:
在为各个方法添加新需求后:体会五种类型的Advice的作用
二、AOP中Advice的类型的基本注解形式
核心:
在配置文件中启用注解功能:
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
①创建类(应该是接口及其实现类,偷懒了):
②编写配置文件:
由于使用注解形式弱化了配置文件的作用,所以配置文件精简了许多
③最核心的部分:编写切面类
package com.high.demo;import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;// 切面类
// AOP注解
@Aspect
public class MyAspectDemo {// 1.前置增强@Before(value = "execution(* com.high.demo.OrderDao.save(..))")public void checkPri(JoinPoint joinPoint) {System.out.println("save方法的前值增强:权限检测..." + joinPoint);}// 2.后置增强@AfterReturning(value = "execution(* com.high.demo.OrderDao.find(..))", returning = "result")public void afterReturn(String result) {System.out.println("find方法的后置增强..." + result);}// 3.环绕增强@Around(value = "execution(* com.high.demo.OrderDao.delete(..))")public Object aroundOne(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println("delete方法的环绕前通知");// 获取接入点Object target = joinPoint.proceed();System.out.println("delete方法的环绕后通知");return target;}// 4.异常通知@AfterThrowing(value = "execution(* com.high.demo.OrderDao.update(..))", throwing="ex")public void afterThrowing(Throwable ex) {System.out.println("update方法的异常通知:Error appeared: " + ex.getMessage());}// 5.最终通知@After(value = "execution(* com.high.demo.OrderDao.update(..))")public void afterAdvice() {System.out.println("This is the After Advice of method update.");}
}
④测试类:
测试类完全使用注解形式了,比之前的先获取配置文件再使用对象及其方法的形式简便了一些
测试结果:
当解除 update 方法的注释 i = 1 / 0 后,代码中出现 0 作分母的错误,此时异常通知就开始起作用了(update 方法未能成功执行,而针对update 方法的最终通知无论如何都会执行)
三、AOP中Advice的类型的切入点注解形式
这是最简便的书写方式了,相对于标题二中的基本注解形式,进一步简化代码,声明切入点的注解,使得不必再对方法的每个新增需求创建切入点,而是对每个原有方法声明切入点,大大减少了需要声明的切入点的个数。
在切面类中写@Aspect注解,并在类中用注解进行切入点的声明(这是注解方式相较于XML配置文件方式简练的点,不再需要在XML配置文件中单独声明切入点并编写织入过程了)
其实实体类、测试类、配置文件相对于标题二下的内容都没有修改,只是在切面类中增加了切入点的注解:
①加入切入点注解的切面类写法:
package com.high.demo2;import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;@Aspect // 最开始给忘喽
public class MyAspect {// AOP切入点的注解,提供更大的灵活性,方便解耦@Pointcut(value = "execution(* com.high.demo2.UserDao.save(..))")private void pointcut1() {}; //此处是一个方法,不是变量@Pointcut(value = "execution(* com.high.demo2.UserDao.find(..))")private void pointcut2() {};@Pointcut(value = "execution(* com.high.demo2.UserDao.delete(..))")private void pointcut3() {};@Pointcut(value = "execution(* com.high.demo2.UserDao.update(..))")private void pointcut4() {};// 1.前置通知@Before(value = "MyAspect.pointcut1()")public void checkPri(JoinPoint joinPoint) {System.out.println("切入点注解测试:save方法的前置通知; " + joinPoint);}// 2.后置通知@AfterReturning(value = "MyAspect.pointcut2()", returning = "result")public void afterOne(String result) {System.out.println("切入点注解测试:find方法的后置通知; " + result);}// 3.环绕通知@Around(value = "MyAspect.pointcut3()")public Object aroundOne(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println("切入点注解测试:delete方法的环绕通知(前);");// 获取接入点Object target = joinPoint.proceed();System.out.println("切入点注解测试:delete方法的环绕通知(后);");return target;}// 4.异常通知@AfterThrowing(value = "MyAspect.pointcut4()", throwing = "ex")public void afterThrowing(Throwable ex) {System.out.println("切入点注解测试:update方法的异常通知; " + ex.getMessage());}// 5.最终通知@After(value = "MyAspect.pointcut4()")public void afterAdvice() {System.out.println("切入点注解测试:update方法的最终通知;");}
}
②测试结果:
(尽管实体类等没有变化,但在切面类书写 Advice 时在熟练之后对各输出语句内容进行了自由发挥,整体代码自认为更容易理解了。)
四、总结
1.后置通知在return语句前输出。
2.异常通知是报错时才会出现的通知,after-throwing 中的after 是指在执行后才能发现异常。
(同时发现:在项目spring03中测试时,按照测试类调用方法的顺序,update执行错误后剩余的delete和find不执行了。)
3.关于最终通知,若异常测试对应的方法(切入点)出错,最终通知会显示在异常测试报错之前,再报错。
4.若所有的新增需求甲方都不要了,我们要改哪些代码?
——在配置文件中将切面类相关的代码删除,保留
<bean name="productDao" class="com.high.demo1.ProductDaoImpl"></bean>
仍可在测试类中以XML配置文件形式使用spring框架对对象进行操作。
5.声明切入点时的expression属性写法(spring的切入点表达式写法):
6.注解有两种:类层面的注解 + 方法/属性层面(类内部)的注解。
7.spring注重团队开发与规则,便于大规模使用。类比自家饭菜与连锁店,自家饭菜一家一个味,但不利于形成规模。
8.代码能力相对容易掌握,但排错能力需要经验与锻炼。日常的节奏是写一段代码,报错,排错,完善,再往下写。
实习笔记—— AOP开发II(AOP中Advice的类型)相关推荐
- 实习笔记 —— springMVC部分II
系列文章目录 实习笔记 -- Spring基础 实习笔记 -- IOC反转控制(xml配置文件 + 注解) 实习笔记 -- AOP开发I 实习笔记 -- AOP开发II(AOP中Advice的类型) ...
- iOS开发笔记之九十四——Swift中的可选类型Optional
一.Optional类型的概念 Swift中为何要引入Optional的概念,官方文档中有介绍: Swift also introduces optional types, which handle ...
- JavaEE——Spring学习笔记03【AOP开发】
JavaEE--Spring学习笔记01[Ioc开发的模式] JavaEE--Spring学习笔记02[Spring和Mybatis的整合] JavaEE--Spring学习笔记03[AOP开发] J ...
- 实习笔记 —— Git II(远程提交)
系列文章目录 实习笔记 -- Spring基础 实习笔记 -- IOC反转控制(xml配置文件 + 注解) 实习笔记 -- AOP开发I 实习笔记 -- AOP开发II(AOP中Advice的类型) ...
- 实习笔记 —— MyBatis II (MyBatis基本数据库操作)
系列文章目录 实习笔记 -- Spring基础 实习笔记 -- IOC反转控制(xml配置文件 + 注解) 实习笔记 -- AOP开发I 实习笔记-- AOP开发II(AOP中Advice的类型) 实 ...
- 实习笔记 —— MyBatis III (输入/输出映射)
系列文章目录 实习笔记 -- Spring基础 实习笔记 -- IOC反转控制(xml配置文件 + 注解) 实习笔记 -- AOP开发I 实习笔记-- AOP开发II(AOP中Advice的类型) 实 ...
- 实习笔记 —— SSM三个框架的整合 V (分页功能)
系列文章目录 实习笔记 -- Spring基础 实习笔记 -- IOC反转控制(xml配置文件 + 注解) 实习笔记 -- AOP开发I 实习笔记 -- AOP开发II(AOP中Advice的类型) ...
- 实习笔记 —— Maven
系列文章目录 实习笔记 -- Spring基础 实习笔记 -- IOC反转控制(xml配置文件 + 注解) 实习笔记 -- AOP开发I 实习笔记 -- AOP开发II(AOP中Advice的类型) ...
- 实习笔记 —— SSM三个框架的整合 III (对后台管理页面进行编写)
系列文章目录 实习笔记 -- Spring基础 实习笔记 -- IOC反转控制(xml配置文件 + 注解) 实习笔记 -- AOP开发I 实习笔记 -- AOP开发II(AOP中Advice的类型) ...
最新文章
- 算法-链表-给定一个数小于该值的在左边等于在中间大于的在右边
- python3 random函数_Python3 中 random模块
- 【数据挖掘】基于密度的聚类方法 - OPTICS 方法 ( 核心距离 | 可达距离 | 族序 )
- bpython使用_使用Python实现一个简单的A/B测试
- Java基础--访问权限控制符
- 作为一名程序员,我站在人生的十字路口
- 6_机器翻译与Seq2Seq模型
- 【MyBatis源码解析】MyBatis一二级缓存
- 熊猫merge()–合并两个DataFrame对象
- php中的数据库操作类、分页类,以及smarty扩展类
- jQuery实现textarea高度根据内容自适应
- 如何制做计算机病毒,电脑病毒制作-怎么制作电脑病毒请教高手,怎么做病毒? – 手机爱问...
- 打开组策略 计算机配置,组策略命令,小编告诉你电脑组策略怎么打开
- OKR工作法学习心得
- 以计算机为主题的想象作文,以想象为话题的作文(通用13篇)
- 解决使用CSV包,将写入字符串写入csv文件时字符串被拆分成很多单元的问题
- FPGA原理和结构简介
- 方案设计阶段目标成本形成过程
- Python sqlalchemy 连接常用的数据库
- Java 应该怎么学
热门文章
- ibatis中配置parameterClass=java.util.HashMap的用法
- 播放失败246106异常代码_三菱-菱云系列电梯故障代码
- 李航:做本质的、严谨的、有意思的研究!
- APACHE官网下载历史版本TOMCAT(以8.5.6版本为例)
- 清理Ubuntu虚拟机磁盘空间
- sublime插件 —— 一键美化HTML/CSS/JS代码
- 东网科技、Rancher Labs联合发布“容器+虚拟化”双引擎超融合平台HOR
- JAVA在线观看视频教程完整版
- seq2seq(序列到序列)模型
- Life Long Learning论文初探————Online Fast Adaptation and Knowledge Accumulation(OSAKA)