做网站有哪些,故城网站建设,营销型网站免费企业网站模版,网站首页html制作代码AOP#xff1a;
springAOP是什么#xff1a;
AOP#xff1a;Aspect Oriented Programming#xff08;面向切面编程、面向方面编程#xff09;#xff0c;其实就是面向特定方法编程。
使用场景#xff1a;
比如你想统计业务中每个方法的执行耗时#xff0c;那我们最…AOP
springAOP是什么
AOPAspect Oriented Programming面向切面编程、面向方面编程其实就是面向特定方法编程。
使用场景
比如你想统计业务中每个方法的执行耗时那我们最初的想法就是对每个方法一开始写一个获取方法运行开始时间然后再来一个获取方法运行结束时间 然后相减那这个做法思路简单不过问题也很明显就是如果都每个方法都这样做我们需要写很多重复的代码所以AOP就可以解决这样的问题
再比如你想知道谁在业务中调用了增删改方法想将这个调用方法的信息存入到信息日志表中我们也可以用AOP来解决这样的问题。
springAOP的代理设计思想
代理模式
二十三种设计模式中的一种属于结构型模式。它的作用就是通过提供一个代理类让我们在调用目标方法的时候不再是直接对目标方法进行调用而是通过代理类间接调用。让不属于目标方法核心逻辑的代码从目标方法中剥离出来——解耦。调用目标方法时先调用代理对象的方法减少对目标方法的调用和打扰同时让附加功能能够集中在一起也有利于统一维护。
生活中的代理 广告商找大明星拍广告需要经过经纪人 合作伙伴找大老板谈合作要约见面时间需要经过秘书 房产中介是买卖双方的代理 太监是大臣和皇上之间的代理 相关术语 静态代理
public class CalculatorStaticProxy implements Calculator {// 将被代理的目标对象声明为成员变量private Calculator target;public CalculatorStaticProxy(Calculator target) {this.target target;}Overridepublic int add(int i, int j) {// 附加功能由代理类中的代理方法来实现System.out.println(参数是 i , j);// 通过目标对象来实现核心业务逻辑int addResult target.add(i, j);System.out.println(方法内部 result result);return addResult;} 静态代理确实实现了解耦但是由于代码都写死了完全不具备任何的灵活性。就拿日志功能来说将来其他地方也需要附加日志那还得再声明更多个静态代理类那就产生了大量重复的代码日志功能还是分散的没有统一管理
动态代理:
动态代理技术分类 JDK动态代理JDK原生的实现方式需要被代理的目标类必须实现接口他会根据目标类的接口动态生成一个代理对象代理对象和目标对象有相同的接口拜把子 cglib通过继承被代理的目标类实现代理所以不需要目标类实现接口认干爹 JDK动态代理技术实现了解
代理工程基于jdk代理技术生成代理对象
AOP的核心概念和执行流程 连接点JoinPoint可以被AOP控制的方法暗含方法执行时的相关信息 通知Advice指哪些重复的逻辑也就是共性功能最终体现为一个方法 切入点PointCut匹配连接点的条件通知仅会在切入点方法执行时被应用 切面Aspect描述通知与切入点的对应关系通知切入点 目标对象Target通知所应用的对象 连接点
在Spring中用JoinPoint抽象了连接点用它可以获得方法执行时的相关信息如目标类名、方法名、方法参数等对于 Around 通知获取连接点信息只能使用 ProceedingJoinPoint 对于其他四种通知获取连接点信息只能使用 JoinPoint 它是 ProceedingJoinPoint 的父类型
JoinPoint的基本方法 String className joinPoint.getTarget().getClass().getName(); //获取目标类名 Signature signature joinPoint.getSignature(); //获取目标方法签名 String methodName joinPoint.getSignature().getName(); //获取目标方法名 Object[] args joinPoint.getArgs(); //获取目标方法运行参数 Object res joinPoint.proceed(); //执行原始方法,获取返回值环绕通知最后一种只有环绕通知能使用
通知类型
1Around环绕通知此注解标注的通知方法在目标方法前、后都被执行如果目标方法有异常那环绕通知的第三格部分结束方法就不会执行 2Before前置通知此注解标注的通知方法在目标方法前被执行 3After 后置通知此注解标注的通知方法在目标方法后被执行无论是否有异常都会执行 4AfterReturning 返回后通知此注解标注的通知方法在目标方法后被执行有异常不会执行这个通知程序必须正常执行才会运行 5AfterThrowing 异常后通知此注解标注的通知方法发生异常后执行这个只有程序有异常了才会运行
从上面几种通知就能看出来第四个和第五个是两个对立的通知。
注意 Around环绕通知需要自己调用 ProceedingJoinPoint.proceed() 来让原始方法执行其他通知不需要考虑目标方法执行 Around环绕通知方法的返回值必须指定为Object来接收原始方法的返回值。拿不到返回值的话界面上就不会显示数据
切入点
切入点表达式描述切入点方法的一种表达式 作用主要用来决定项目中的哪些方法需要加入通知 Advice 常见形式 1execution(……)根据方法的签名来匹配 2annotation(……) 根据注解匹配
切入点表达式的语法 execution(访问修饰符? 返回值 包名.类名.?方法名(方法参数) throws 异常?) 例子execution(public void com.springboottlias.service.impl.DeptServiceImpl.deletedept(java.lang.Integer))
访问修饰符可省略比如: public、protected
切入点表达式中的通配符* 和 ..
* 单个独立的任意符号可以通配任意返回值、包名、类名、方法名、任意类型的一个参数也可以通配包、类、方法名的一部分 例子execution(* com.*.service.*.update*(*)) 第一个*表示任意返回值 第二个*表示com包下的任意包 第三个*也表示service的包名或类名 第四个*表示方法名中开头是update的方法名如果是*deptservice这样的说明以deptservice结尾的方法名 第五个*表示update*方法中任意的一个参数
.. 多个连续的任意符号可以通配任意层级的包或任意类型、任意个数的参数 例子execution(* com.itheima..DeptService.*(..)) 表示这个函数里面可以有任意个参数。
AOP执行流程 一旦我们进行了AOP的方法开发那我们运行得就不是原始对象得方法了运行得就是一个代理对象 这个代理对象如何理解呢可以理解为是原始对象方法得加强版这个加强得意思就是在这个代理对象中多了其它的方法 当我们想执行原来的原始对象方法这个时候我们就不是执行原始对象我们执行的就是这个代理对象。 AOP案例
将案例中 增、删、改 相关接口的操作日志记录到数据库表中 日志信息包含操作人、操作时间、执行方法的全类名、执行方法名、方法运行时参数、返回值、方法执行时长
1准备
这个准备包括引入AOP的依赖然后建一个日志记录表还有一个对呀日志记录表的实体类
1在案例工程中引入AOP的起步依赖
!-- AOP依赖 --dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-aop/artifactId/dependency2导入资料中准备好的数据库表结构并引入对应的实体类
下面是实体类
Data
AllArgsConstructor
NoArgsConstructor
public class OperateLog {private Integer id; //IDprivate Integer operateUser; //操作人IDprivate LocalDateTime operateTime; //操作时间private String className; //操作类名private String methodName; //操作方法名private String methodParams; //操作方法参数private String returnValue; //操作方法返回值private Long costTime; //操作耗时
}Sql脚本
-- 操作日志表
create table operate_log(id int unsigned primary key auto_increment comment ID,operate_user int unsigned comment 操作人ID,operate_time datetime comment 操作时间,class_name varchar(100) comment 操作的类名,method_name varchar(100) comment 操作的方法名,method_params varchar(1000) comment 方法参数,return_value varchar(2000) comment 返回值,cost_time bigint comment 方法执行耗时, 单位:ms
) comment 操作日志表;
2自定义注解 Log
Retention(RetentionPolicy.RUNTIME)
Target(ElementType.METHOD)
public interface Log {
}
3定义切面类完成记录操作日志的逻辑
Slf4j
Component//将这个类交给IOC容器管理
Aspect//声明这个类是一个AOP类
public class OperateLogAspect{Autowiredprivate HttpServletRequest request;Autowiredprivate OperateLogMapper operateLogMapper;Pointcut(annotation(com.springboottlias.anno.Log))private void pt(){}Around(pt())public Object RecordtoDatebase(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {//操作人ID - 当前登录员工ID//获取请求头中的jwt令牌解析令牌String jwt request.getHeader(token);Claims claims JwtUtils.parseJWT(jwt);Integer operateUserId (Integer) claims.get(id);//操作时间LocalDateTime operateTime LocalDateTime.now();//操作类名String classname proceedingJoinPoint.getTarget().getClass().getName();//操作方法名String methodname proceedingJoinPoint.getSignature().getName();//操作方法参数Object[] args proceedingJoinPoint.getArgs();String methodParams Arrays.toString(args);long begin System.currentTimeMillis();//原始方法执行之前的时间//调用原始目标方法运行Object res proceedingJoinPoint.proceed();//方法返回值String returnValue JSONObject.toJSONString(res);//操作耗时long end System.currentTimeMillis();//原始方法执行之后的时间long costtime end-begin;//记录操作日志OperateLog operateLog new OperateLog(null,operateUserId,operateTime,classname,methodname,methodParams,returnValue,costtime);operateLogMapper.insert(operateLog);log.info(AOP操作日志{},operateLog);return res;}
}
这一步有几个注意点
1你想要获得操作人的ID就得用到JWT令牌功能你得先从请求头中获得jwt令牌并且解析token 现在的问题就转化为了你怎么得到这个令牌我们知道令牌是在请求头中的请求头的对象是Request 所以我们可以从IOC容器中获得Request对象然后获取令牌。 Autowired private HttpServletRequest request;
//操作人ID - 当前登录员工ID //获取请求头中的jwt令牌解析令牌 String jwt request.getHeader(token); Claims claims JwtUtils.parseJWT(jwt); Integer operateUserId (Integer) claims.get(id); 2第二个处理的点就是这个方法返回值这边的处理 用到了之前的一个工具类将对象转化成json格式的数据。 4在需要的方法上添加注解Log 事务
简单理解事务就是不可拆分的最小事件
Spring事务管理底层是AOP
位置业务service层的方法上、类上、接口上 作用将当前方法交给spring进行事务管理方法执行前开启事务成功执行完毕提交事务出现异常回滚事务
Transactional这个注解可以作用在方法接口和类上不过我们一般作用在业务层的增删改业务上也就是需要访问多次数据访问的方法上。
TransactionalOverridepublic void deletedept(Integer id) {deptmapper.deletedept(id);//根据id删除部门int i 1/0;empMapper.deleteByDeptid(id);//根据部门id删除部门下的员工}
通过这个方法可以解决方法中出现RuntimeError也就是运行时错误 但是如果你去特意抛一个异常那还是解决不了比如下面
TransactionalOverridepublic void deletedept(Integer id) throws Exception {deptmapper.deletedept(id);//根据id删除部门if(true){throw new Exception(错误);}empMapper.deleteByDeptid(id);//根据部门id删除部门下的员工}
这个时候就需要用到spring事务中的一个回滚事务注释Transactional(rollbackFor Exception.class)
Transactional(rollbackFor Exception.class)Overridepublic void deletedept(Integer id) throws Exception {deptmapper.deletedept(id);//根据id删除部门if(true){throw new Exception(错误);}empMapper.deleteByDeptid(id);//根据部门id删除部门下的员工}
这样处理之后所有的异常都会回滚
事务属性-传播行为
事务传播行为指的就是当一个事务方法被另一个事务方法调用时这个事务方法应该如何进行事务控制。
设想一个场景在一个事务里又开启了另一个事务那这个时候这两个事务的回滚或者叫传播行为是怎么样的呢 这个注解可以解释Transactional(propagation Propagation.REQUIRED) REQUIRED 【默认值】需要事务有则加入无则创建新事务 REQUIRES_NEW 需要新事务无论有无总是创建新事务
当这个注解的值是这个的时候就说明两个事务时绑定在一起的比如在delete这个方法中又新建了一个事务然后delete方法因为 异常rollback了那这个事务也得rollback。
但如果你设置的值是这个Transactional(propagation Propagation.REQUIRES_NEW) 那这个时候就会新开一个事务就算上面的delete方法rollback了你这个事务还是会接着执行。
propagation Propagation.REQUIRES_NEW比如下订单前需要记录日志不论订单保存成功与否都需要保证日志记录能够记录成功。
举个例子
Transactional
public void removeDepartmentAndEmployees(Integer deptId) { deletedept(deptId); // 调用配置了 REQUIRES_NEW 的方法
} Transactional(propagation Propagation.REQUIRES_NEW)
Override
public void deletedept(Integer id) { deptMapper.deletedept(id); // 如果这条操作成功 empMapper.deleteByDeptid(id); // 假设这条操作失败
} 在上面的例子中假设 deletedept 方法中的 deptMapper.deletedept(id) 调用成功但 empMapper.deleteByDeptid(id) 调用失败
如果 deletedept 使用了 REQUIRES_NEW则 deptMapper.deletedept(id) 将成功提交即使后面的 empMapper.deleteByDeptid(id) 失败部门的删除操作仍然会被提交成功。
这个功能还是挺强大的不过也需要主要是否会发生数据不一致的问题 文章转载自: http://www.morning.rlxg.cn.gov.cn.rlxg.cn http://www.morning.jzklb.cn.gov.cn.jzklb.cn http://www.morning.xlndf.cn.gov.cn.xlndf.cn http://www.morning.dhqyh.cn.gov.cn.dhqyh.cn http://www.morning.mxhcf.cn.gov.cn.mxhcf.cn http://www.morning.mnclk.cn.gov.cn.mnclk.cn http://www.morning.xkhhy.cn.gov.cn.xkhhy.cn http://www.morning.mrttc.cn.gov.cn.mrttc.cn http://www.morning.lcmhq.cn.gov.cn.lcmhq.cn http://www.morning.ycnqk.cn.gov.cn.ycnqk.cn http://www.morning.lyzwdt.com.gov.cn.lyzwdt.com http://www.morning.fxqjz.cn.gov.cn.fxqjz.cn http://www.morning.pcxgj.cn.gov.cn.pcxgj.cn http://www.morning.rlpmy.cn.gov.cn.rlpmy.cn http://www.morning.txlxr.cn.gov.cn.txlxr.cn http://www.morning.bgpch.cn.gov.cn.bgpch.cn http://www.morning.rhkmn.cn.gov.cn.rhkmn.cn http://www.morning.cnbdn.cn.gov.cn.cnbdn.cn http://www.morning.nbrkt.cn.gov.cn.nbrkt.cn http://www.morning.hfrbt.cn.gov.cn.hfrbt.cn http://www.morning.swsrb.cn.gov.cn.swsrb.cn http://www.morning.rwtlj.cn.gov.cn.rwtlj.cn http://www.morning.cfpq.cn.gov.cn.cfpq.cn http://www.morning.nfzw.cn.gov.cn.nfzw.cn http://www.morning.gnghp.cn.gov.cn.gnghp.cn http://www.morning.klzdy.cn.gov.cn.klzdy.cn http://www.morning.httzf.cn.gov.cn.httzf.cn http://www.morning.fwcnx.cn.gov.cn.fwcnx.cn http://www.morning.xpgwz.cn.gov.cn.xpgwz.cn http://www.morning.guangda11.cn.gov.cn.guangda11.cn http://www.morning.gjlxn.cn.gov.cn.gjlxn.cn http://www.morning.mwmtk.cn.gov.cn.mwmtk.cn http://www.morning.chbcj.cn.gov.cn.chbcj.cn http://www.morning.bryyb.cn.gov.cn.bryyb.cn http://www.morning.heleyo.com.gov.cn.heleyo.com http://www.morning.bsxws.cn.gov.cn.bsxws.cn http://www.morning.nfmtl.cn.gov.cn.nfmtl.cn http://www.morning.mkzdp.cn.gov.cn.mkzdp.cn http://www.morning.xprzq.cn.gov.cn.xprzq.cn http://www.morning.yrdkl.cn.gov.cn.yrdkl.cn http://www.morning.gnjkn.cn.gov.cn.gnjkn.cn http://www.morning.yfmlj.cn.gov.cn.yfmlj.cn http://www.morning.mlntx.cn.gov.cn.mlntx.cn http://www.morning.rdnpg.cn.gov.cn.rdnpg.cn http://www.morning.lcplz.cn.gov.cn.lcplz.cn http://www.morning.tqldj.cn.gov.cn.tqldj.cn http://www.morning.zybdj.cn.gov.cn.zybdj.cn http://www.morning.rbylq.cn.gov.cn.rbylq.cn http://www.morning.tnhg.cn.gov.cn.tnhg.cn http://www.morning.ccsdx.cn.gov.cn.ccsdx.cn http://www.morning.wyjhq.cn.gov.cn.wyjhq.cn http://www.morning.mmynk.cn.gov.cn.mmynk.cn http://www.morning.nfzzf.cn.gov.cn.nfzzf.cn http://www.morning.jqjnx.cn.gov.cn.jqjnx.cn http://www.morning.bncrx.cn.gov.cn.bncrx.cn http://www.morning.kqbjy.cn.gov.cn.kqbjy.cn http://www.morning.hyyxsc.cn.gov.cn.hyyxsc.cn http://www.morning.zcckq.cn.gov.cn.zcckq.cn http://www.morning.jmdpp.cn.gov.cn.jmdpp.cn http://www.morning.nccqs.cn.gov.cn.nccqs.cn http://www.morning.czqqy.cn.gov.cn.czqqy.cn http://www.morning.jqhrk.cn.gov.cn.jqhrk.cn http://www.morning.ttxnj.cn.gov.cn.ttxnj.cn http://www.morning.rjmg.cn.gov.cn.rjmg.cn http://www.morning.kqgsn.cn.gov.cn.kqgsn.cn http://www.morning.pntzg.cn.gov.cn.pntzg.cn http://www.morning.pmnn.cn.gov.cn.pmnn.cn http://www.morning.kdtdh.cn.gov.cn.kdtdh.cn http://www.morning.nqfxq.cn.gov.cn.nqfxq.cn http://www.morning.lnbcx.cn.gov.cn.lnbcx.cn http://www.morning.rqjfm.cn.gov.cn.rqjfm.cn http://www.morning.hnpkr.cn.gov.cn.hnpkr.cn http://www.morning.swimstaracademy.cn.gov.cn.swimstaracademy.cn http://www.morning.lqpzb.cn.gov.cn.lqpzb.cn http://www.morning.ntqjh.cn.gov.cn.ntqjh.cn http://www.morning.lyzwdt.com.gov.cn.lyzwdt.com http://www.morning.ylph.cn.gov.cn.ylph.cn http://www.morning.pxwzk.cn.gov.cn.pxwzk.cn http://www.morning.pxbrg.cn.gov.cn.pxbrg.cn http://www.morning.cznsq.cn.gov.cn.cznsq.cn