大数据WEB阶段Spring框架 AOP面向切面编程(二)
Spring AOP面向切面编程(二)
一、切入点的execution表达式
execution的表达形式: execution(修饰符? 返回值类型 所在包类? 方法名(参数列表) 异常?)
- ?表示可有可无
execution(public * *(..))
工程中所有的public方法
execution(* set*(..))
工程中所有方法名以set开头的方法
execution(* com.xyz.service.AccountService.*(..))
com.xyz.service.AccountService类下面的所有方法
execution(* com.xyz.service..(..))
com.xyz.service包下所有类的所有方法
execution(* com.xyz.service...(..))
com.xyz.service包下及其子包下所有类的所有方法
execution(* com.xyz..service..(..))
报名以com.xyz开头的所有子包一直子到service下的所有类的所有方法
举例:com.xyz.a.b.service com.xyz.a.service com.xyz.a.b.c.service 会满足上面的条件- ?表示可有可无
二、五大通知的具体实现
- 环绕通知 around
- 5个中最强大的通知,唯一一个能在通知中控制目标方法是否执行的通知
- 5个中最强大的通知,唯一一个能在通知中控制目标方法是否执行的通知
- 前置通知
- 配置文件配置
- 后置通知
- 配置文件配置
- 异常通知
- 异常通知可以控制出现异常后事务回滚 , 和记录日志
- 配置文件配置
- 注意: JoinPoint参数必须放在第一位
- 最终通知
- 不管是么情况都会执行
三、AOP注解
- 在配置文件中把aop注解开关打开
- 通过注解配置切面类
- 通过注解配置通知方法
- 前置通知
- 后置通知
- 环绕通知
- 异常通知
- 最终通知
- 前置通知
四、通过注解生成切入点表达式的引用
- 创建一个空方法
- 使用@Pointcut注解生成一个切入点的引用
- 使用
- 使用@Pointcut注解生成一个切入点的引用
五、环绕嵌套问题
六、自定义注解
- 声明一个注解
- 使用
- 判断是否有注解
七、各种示例
异常
代码结构如图所示 PersonServlet PersonService PersonDao 用异常通知捕获servlet的所有的方法抛出的异常: 目标对象所在的类 cn.tedu.big1601.servlet.PersonServlet 抛出异常所在的方法 save() 抛出异常的名称 XxxException 异常信息 message 意义: 异常处理类和业务逻辑类完全松耦合。 时刻捕获生产生产环境中所有的错误,实时监控该系统,异常收集。 @Component @Aspect public class ExceptionAspect { @AfterThrowing(value = "execution(* com.tj..*(..))" ,throwing = "throwable" ) public void after(JoinPoint jp , Throwable throwable){ System.out.println("异常发生在:"+jp.getTarget().getClass()); System.out.println(jp.getSignature().getName()+"()发生了异常!"); System.out.println("发生异常类型:"+throwable.getClass()); System.out.println("异常信息:"+throwable.getMessage()); } }
统计方法执行时间
计算servlet的各个类的各个方法的执行时间 1.类的名称 2.方法的名称 3.执行的时间 控制台输出 意义:用来监控程序的性能问题 @Component @Aspect public class RuntimeAspect { @Around("execution(* com.tj..*(..))") public Object around(ProceedingJoinPoint pjp) throws Throwable{ Long begin = System.currentTimeMillis(); Object result = pjp.proceed(); Long end = System.currentTimeMillis(); System.out.println(pjp.getTarget().getClass()+"类"+pjp.getSignature().getName()+"方法执行了"+ (end - begin)+"毫秒!"); return result; } }
事务控制
当方法上有事务的注解,该方法就有事务。 写一个切面来完成 事务控制类 public class TxManage { /** * 开启事务 * */ public static void stattx(){ System.out.println("开启了事务"); } /** * 提交事务 * */ public static void commitTx(){ System.out.println("提交事务"); } /** * 回滚事务 * */ public static void rollback(){ System.out.println("事务回滚"); } } 自定义事务注解 @Target(value = { ElementType.METHOD }) @Retention(value = RetentionPolicy.RUNTIME) public @interface TxAnnotation { String value() default ""; } 给需要事务控制的地方添加注解 @Component public class PersonServiceImpl implements PersonService{ @Autowired private PersonDao dao; @TxAnnotation @Cacheable("add") @Override public void savePerson(Person person) { dao.savePerson(person); } @TxAnnotation @Cacheable("get") @Override public Person getPerson(int id) { Person person = dao.getPerson(id); return person; } @TxAnnotation @Cacheable("del") @Override public void delPerson(int id) { dao.delPerson(id); } } 事务控制切面 @Component @Aspect public class TxAspect { @Around(value = "execution(* com.tj..*(..)) && @annotation(ann)") public Object around(ProceedingJoinPoint pjp ,TxAnnotation ann ) throws Throwable{ Object result = null; try{ TxManage.stattx(); result = pjp.proceed(); TxManage.commitTx(); }catch(Exception e){ TxManage.rollback(); } return result; } }
权限控制
说明:每个方法上添加能够执行该方法的注解@PrivilegeInfo 并且要指明 PrivilegeInfo(name=”add”) 那么将来这个方法只能执行还有add权限的方法 自定义权限控制注解 @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface PrivilegeInfo { String value() ; } 给需要控制权限的地方添加权限控制注解 @Component public class PersonServlet { @Autowired private PersonService ps; /** * 保存用户信息 * */ @PrivilegeInfo("add") public void savePerson(Person person){ // int i = 1/0; ps.savePerson(person); } /** * 获取用户信息 * */ @PrivilegeInfo("get") public Person getPerson(int id){ Person person = ps.getPerson(id); return person ; } /** * 删除用户信息 * */ @PrivilegeInfo("del") public void delPerson(int id ){ ps.delPerson(id); } } 权限控制切面类 @Component @Aspect public class PrivilegInfoAspect { //当前用户的权限 List<String> list =Arrays.asList("add" , "get"); @Around("execution(* com.tj..*(..)) && @annotation(ann)") public Object around(ProceedingJoinPoint pjp , PrivilegeInfo ann) throws Throwable{ String value = ann.value(); Object result = null; if(list.contains(value)){ System.out.println("尊敬的飞秋会员你好!"); result = pjp.proceed(); }else{ System.out.println("你没有这个权限 ,滚"); } return result; } }
数据缓存
缓存需求:1.savePerson的时候需要往数据库里保存一份然后再往内存(Map)中保存一份 2.getPerson的时候先从Map中获取 如果有则返回则不用执行目标方法,如果内存中没有则执行目标方法从数据库取 3.如果第一次调用getPerson内存中没有的话 执行目标方法从数据库取 取出来后同时把获取到的Person对象保存到内存中,以便后续获取时直接从内存中取 自定义 缓存控制注解 @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Cacheable { String value(); } 给需要缓存的地方添加注解 @Component public class PersonServiceImpl implements PersonService{ @Autowired private PersonDao dao; @TxAnnotation @Cacheable("add") @Override public void savePerson(Person person) { dao.savePerson(person); } @TxAnnotation @Cacheable("get") @Override public Person getPerson(int id) { Person person = dao.getPerson(id); return person; } @TxAnnotation @Cacheable("del") @Override public void delPerson(int id) { dao.delPerson(id); } } 缓存控制切面类 @Component @Aspect public class CacheableAspect { //缓存 Map<Integer , Person> map = new HashMap<Integer,Person>(); @Around("execution(* com.tj..*(..))&& @annotation(ann)") public Object befer(ProceedingJoinPoint jp , Cacheable ann) throws Throwable{ Object result = null; String v = ann.value(); if(v.equals("add")){ Person person = (Person) jp.getArgs()[0]; int id = person.getId(); if(map.containsKey(id)){ System.out.println("该用户已存在"); }else{ System.out.println("存入 缓存"); map.put(id, person); result = jp.proceed(); } }else if(v.equals("get")){ int id = (Integer) jp.getArgs()[0]; if(map.containsKey(id)){ System.out.println("从缓存中获取"); result = map.get(id); }else{ result = jp.proceed(); Person person = (Person) result; map.put(person.getId(), person); } } return result; } }
智能推荐
zabbix远程命令执行
zabbix可以通过远程发送执行命令或脚本来对部分的服务求故障进行修复 zabbix客户端配置 设置zabbix客户端用户的sudo权限 在客户端的配置文件zabbix_agentd.conf中添加下面语句,开启对远程命令的支持,添加完成后重启下服务 输入下面命令手动检测,有内容则表示远程命令可用,否则提示remote commands are not enable 在119服目录/data下添加...
机器学习中K-means聚类算法的原理及实现(Python)
背景知识 K-means聚类算法是一种流行于数据挖掘领域的无监督学习算法。K-means聚类算法的目的是:把已知的 n个点划分到k个聚类中,使得每个点都属于离它最近的点(聚类中心)对应的聚类。 在完成该算法的过程中,找到k个聚类中心是关键。 算法介绍 我们先介绍几个基本概念: 簇:数据点的集合,每一个簇中的对象是相似的。 质心:簇中所有点的中心(由计算所有点坐标的均值可得)。 比如在这幅图中,我们...
接口回调基础理解
接口回调听起来好像很厉害的样子,但其实只要能够搞清楚代码的执行过程,多看几遍,并且认真思考,再加上勤奋的练习,熟练掌握简单的接口回调并不是难题,接下来,我会用一个简单的例子,来带大家一起分析代码的执行过程,以及这样写的好处,以及这样写的思路。 我们知道recyclerView是没有自带点击事件的,所以这里我们就拿给recyclerView添加点击事件为例。 ok 我们做好了一个简单的recycer...
Mac下的myeclipse安装
1.首先要安装jdk跟jre 2.安装过程中可能会遇到您需要安装旧 Java SE 6 运行环境才能打开此 Java 应用程序的提示 解决办法就是安装ava for os x 2015-001.,这里不要点系统给你提示的界面,根本没法下载 我上传的链接,可以直接下载:链接: https://pan.baidu.com/s/1qYbT6os 密码: x...
30分钟实战树莓派连接到微软云Azure IoT Hub并将数据可视化
更多内容,关注公众号: 树莓派是很多动手达人必备的小玩具,本节内容,让我们拿出树莓派,在30分钟内,将树莓派连接到微软云Azure的IoT Hub,然后将温湿度曲线可视化。 本实战完整视频: 树莓派连接到Azure IoT Hub 并用时序见解展示数据 本节内容中,树莓派发送的数据是模拟出来的,并没有真实的连接到传感器,您可以选购不同的传感器来采集真实的环境信息。 Azure IoT Hub 为我...
猜你喜欢
spring cloud gateway 整合ribbon、nacos discovery实现负载均衡源码简析
1 spring cloud gateway 负载均衡入口 spring cloud gateway 使用 LoadBalancerClientFilter 来实现载均衡的功能,该过滤器通过LoadBalancerClient.choose(ServerWebExchange exchange)方法来获取目标实例。 LoadBalancerClient 为spring-cloud-commons包...
VUE快速搭建项目
作为一个前端小辣鸡 今天在网上找到了 一个 快速 无脑式搭建vue项目的方式 分享一下 我们采用图形界面创建项目。通过 vue ui 命令启动 vue cli service 后,访问 http://localhost:8000/project/create 可以直接进入项目创建流程。 步骤中有些地方值得一提 详情:包管理器指定 npm,后续在npm 配置文件(.npmrc)中可手动指定国内镜像源...
2017-8-10 Struts2学习笔记二
一、web.xml文件的编写 1. 由于struts2是用过滤器拦截请求的,所以需要在web.xml文件中配置一个过滤器。 2. 这个过滤器的名字叫StrutsPrepareAndExecuteFilter,中文名曰struts准备和执行过滤器,就是这个过滤器拦截我们在地址栏的请求。 3. 查找这个过滤器,将它的全路径写在filter-class标签中,eclipse可以使用Shift+Ctrl+...
Windows Terminal配置Git
文章目录 Windows Terminal配置Git 效果 下载和安装 配置Windows Terminal 配置其它命令行 Windows Terminal配置Git 效果 先上效果图: 下载和安装 Windows Terminal是微软开发的面向命令行用户的全新,现代,功能丰富,高效的终端应用程序。 它包括Windows命令行社区最常请求的许多功能,包括对选项卡,富文本,全球化,可配置性,主题...
CW MCU v11.1学习笔记1
说明:通过处理器专家创建芯片为MC9S08DZ60的工程,按键控制LED 一、CW11.1软件界面布局 1、双击桌面图标,打开软件,设置工作空间 软件主界面 调试界面 处理器专家界面 有时经常调整(删除)面板布局,如果想恢复布局,可在Window工具栏下的Reset Perspective选项来复位面板布局 二、新建工程 1、在C/C++模式下,在Commander面板下点击New MCU pro...