Spring Aop及事务管理

5 Spring AOP

AOP概述

    AOP:全称是 Aspect Oriented Programming 即:面向切面编程。简单的说它就是把我们程序重复的代码抽取出来,在需要执行的时候,使用动态代理的技术,在不修改源码的基础上,对我们的已有方法进行增强。Aop的作用:在程序运行期间,不修改源码对已有方法进行增强。Aop优势:减少重复代码、提高开发效率、维护方便AOP的实现方式:使用动态代理技术

Spring AOP常用术语

Joinpoint( 连接点)

所谓连接点是指那些被拦截到的点。在 spring 中,这些点指的是方法,因为 spring 只支持方法类型的连接点。即实际增强功能的方法

Pointcut( 切入点)

所谓切入点是指我们要对哪些 Joinpoint 进行拦截的定义。一个类中所有的方法都可以是切入点,Spring Aop中切入点只能是方法。所以我么你可以把切入点理解成:目标对象里面所有的方法都称为切入点

Advice( 通知/ 增强)

Advice可以翻译成通知,也有人称为增强。所谓通知是指拦截到 Joinpoint 之后所要做的事情就是通知。即我们要给目标方法实际提供的增强代码就是增强。那么根据增强代码书写的位置不同,增强可以分为以下几类:

前置通知,后置通知,异常通知,最终通知,环绕通知。

Target( 目标对象)

 要被增强功能的对象就是目标对象。

Proxy(代理)

一个类被 AOP 织入增强后,就产生一个结果代理类。

Aspect( 切面)

Aspect称为切面。切面是切入点和增强的结合。通过代码会发现,增强功能所在的类称为切面类,里面配置的是增强和切入点的都是切面

案例:Spring AOP

  • pom.xml引入AOP的依赖

    <dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>5.2.25.RELEASE</version>
    </dependency>
    
  • 定义目标对象

    @Component
    public class Calculator {public int add(int num1,int num2){int sum = num1 + num2;return sum;}public int div(int num1,int num2){int sum = num1 / num2;return sum;}
    }
    
  • 定义切面类,增强功能所在的类称为切面类

    @Component
    @Aspect //切面
    public class LoggerAdvice {public void before(){System.out.println("xxx方法被调用了,传入的参数是:...");}public void after(){System.out.println("xxx方法执行完毕了,执行结果是:...");}public void afterThrowing(){System.out.println("xxx方法被执行出错了,出现的异常是:...");}
    }
    
  • 指定通知类型,通知就是指实际要增强的代码

    @Component
    @Aspect //切面
    public class LoggerAdvice {//指定增强代码实际织入位置:切入点代码执行前//    @Before(一个程序中有N个类,具体想给哪些类做增强) //定义切入点@Before("execution(* com.woniu.demo.Calculator.add(int,int))")public void before(){System.out.println("xxx方法被调用了,传入的参数是:...");}//指定增强代码实际织入位置:切入点代码执行后@AfterReturning("execution(* com.woniu.demo.Calculator.add(int,int))")public void after(){System.out.println("xxx方法执行完毕了,执行结果是:...");}//指定增强代码实际织入位置:切入点代码执行出错时@AfterThrowing("execution(* com.woniu.demo.Calculator.add(int,int))")public void afterThrowing(){System.out.println("xxx方法被执行出错了,出现的异常是:...");}
    }
    
  • 在Spring的配置类上开启spring aop的代理模式,并选择代理方式
    @Configuration //通知spring容器,这个类与别的类不一样,是一个配置类,用于初始化spring容器的一个类

    @ComponentScan(basePackages = {"com.woniu.dao","com.woniu.service","com.woniu.controller","com.woniu.target"}) 
    @EnableAspectJAutoProxy(proxyTargetClass = true) //开启aop代理 proxyTargetClass选择代码模式true:cglib false:jdk代理
    public class SpringConfig {
    }
    

    proxyTargetClass默认值是false,代表的是如果目标类是有接口的使用jdk的proxy代理,如果没有接口使用cglib;如果将proxyTargetClass设置为true,那么不管目标类是实现了接口,都会使用cglib进行代理。

  • 测试代理对象,观察增强功能是否增强成功

    //1.通知测试类,使用的spring的测试
    @RunWith(SpringJUnit4ClassRunner.class)  //通知测试类基于spring提供的单元测试
    //注解里面赋值,省略属性名,属性值赋值value,class指定配置类的字节码
    @ContextConfiguration(classes = SpringConfig.class)//指定测试时,基于哪个spring的配置文件测试
    public class MySpringTester {@Autowiredprivate Calculator calculator; //最终注入时就是代理对象@Test //java的junit框架提供的注解public void test03(){//输出:class com.woniu.demo.Calculator$$EnhancerBySpringCGLIB$$d89ada67System.out.println(calculator.getClass());calculator.add(1,1);}
    }
    

    测试效果如下所示:
    在这里插入图片描述

在 spring 中,框架会根据目标类是否实现了接口来决定采用哪种动态代理的方式。

切入点表达式【会读会用】

语法:
execution( [权限修饰符] 返回值类型 包名.类名.方法名(参数列表) )
举例:execution(public int com.woniu.Calculator.div(int,int))简化execution(int com.woniu.Calculator.div(int,int))
提示:语法中出现[]包裹的内容都是可选的

常见的切入点案例

1. execution(public * *(..)) 所有的public的方法2. execution(* com.spring.aop.*(..))所有的aop包下的所有类的方法(不包含子包) 3. execution(* com.spring.aop..*(..))所有的aop包及其子包下的所有类的方法.切入点表达式:execution(* com.woniu..*(..))  *表示返回值类型、类名、方法名不限  (..)参数列表不限制4. execution(* com.spring.aop.IOrderService.*(..))IOrderService接口中定义的所有方法5. execution(* com.spring.aop.IOrderService+.*(..))匹配实现特定接口所有类的方法 IOrderServiceIOrderService+ 举例:IOrderService1 IOrderServiceImpl 不能匹配IOrderService   IOrderService* 举例:IOrderService1 IOrderServiceImpl 匹配IOrderService   6. execution(* save*(..))去匹配所有以save开头的方法 save save1 save2

AOP增强分类

前置通知@Before

作用 用于配置前置通知。指定增强的方法在切入点方法之前执行
属性:method:用于指定通知类中的增强方法名称ponitcut-ref:用于指定切入点的表达式的引用poinitcut:用于指定切入点表达式
执行时间点: 切入点方法执行之前执行

后置通知@AfterReturning

作用:用于配置后置通知
属性:method:指定通知中方法的名称。pointct:定义切入点表达式pointcut-ref:指定切入点表达式的引用
执行时间点:切入点方法正常执行之后。它和异常通知只能有一个执行

异常通知@AfterThrowing

作用:用于配置异常通知,切入点方法发生异常时才执行属性:method:指定通知中方法的名称。pointcut:定义切入点表达式pointcut-ref:指定切入点表达式的引用
执行时间点:切入点方法执行产生异常后执行。它和后置通知只能执行一个

注意:目标行为只有抛出了异常之后才会执行这个增强方法

最终通知@After

作用:用于配置最终通知
属性:method:指定通知中方法的名称。pointct:定义切入点表达式pointcut-ref:指定切入点表达式的引用
执行时间点: 无论切入点方法执行时是否有异常,它都会在其后面执行。

无论是否有异常,最终通知都会执行

案例1:利用前置、后置、异常和最终增强完成日志管理

  • 目标类

    @Component
    public class Calculator implements ICalculator{public int sum(int num1,int num2){System.out.println("......目标方法sum执行");int sum = num1 + num2;return sum;}public int sub(int num1,int num2){int result = num1 - num2;return result;}public int plus(int num1,int num2){int result = num1 * num2;return result;}public int div(int num1,int num2){int result = num1 / num2;return result;}
    }
    
  • 切面类

    @Aspect 
    @Component
    public class LoggerAdvance {//抽取公共切入点@Pointcut("execution(* com.woniu.target..*(..))")public void myPointCut(){}/**** @param jp 连接点,AOP实际增强功能的哪个方法 不用程序员传值,spring aop赋值*///前置增强(切入点表达式)@Before("myPointCut()")public void before(JoinPoint jp){//方法签名Signature signature = jp.getSignature();String methodName = signature.getName();//实参列表Object[] args = jp.getArgs();System.out.println(methodName+"方法被调用了,用户传入的参数分别是:"+ Arrays.toString(args));}/**** @param jp* @param result @AfterReturning后置增强,用来接收即将返回的值,程序员不管,spring aop注入*/@AfterReturning(value = "myPointCut()",returning = "result")//returning属性作用将方法执行结果注入程序员指定的参数中public void afterReturning(JoinPoint jp, Object result){System.out.println(jp.getSignature().getName()+"方法执行完毕,执行结果是:"+result);}/*** 异常增强,切入点方法执行出错时,实现的增强* @param e  用来保存spring aop做异常增强时,实际发生的异常对象*/@AfterThrowing(value = "myPointCut()",throwing = "e")public void afterThrowing(JoinPoint jp,Throwable e){System.out.println(jp.getSignature().getName()+"执行出错啦,出现的错误是:"+e);}/*** 最终增强,切入点方法执行过程不管有没有异常,始终会执行的代码 finally{}中的代码*/@After("myPointCut()")public void after(){System.out.println("无论代码是否出错,你都可以看到这行输出语句 释放哪些资源");}
    }
    
  • 测试代码

    @Autowired
    private ICalculator proxy; //代理对象 JDK:代理类 implements ICalculator  CGLIB extends Calculator
    @Test
    public void mt02(){proxy.div(12,0);
    }
    

使用@Pointcut注解定义公用切入点

在每一个通知中定义切点,工作量大,不方便维护,我们可以使用@pointcut来声明切点

切点允许逻辑运算 例如mypointcut()||mypointcut1()

6 环绕增强

环绕通知@Around

环绕增强功能是spring aop五种增强里面最厉害!!使用最灵活!!

作用:环绕通知,它是spring框架为我们提供的一种可以在代码中手动控制增强方法何时执行的方式。
属性:method:指定通知中方法的名称。pointcut:定义切入点表达式pointcut-ref:指定切入点表达式的引用

注意:通常情况下,环绕通知都是独立使用的

案例:利用环绕增强完成日志管理

  • 目标类

    @Component
    public class Calculator implements ICalculator{public int sum(int num1,int num2){System.out.println("......目标方法sum执行");int sum = num1 + num2;return sum;}public int sub(int num1,int num2){int result = num1 - num2;return result;}public int plus(int num1,int num2){int result = num1 * num2;return result;}public int div(int num1,int num2){int result = num1 / num2;return result;}
    }
    
  • 切面类

    @Component
    @Aspect
    public class LoggerAdvicer {@Around("execution(* com.woniu.demo..*(..))")public Object around(ProceedingJoinPoint pjp){try {System.out.println(pjp.getSignature().getName()+"方法被调用了xxx传入的参数是:"+ Arrays.toString(pjp.getArgs()));//指定目标对象的方法正在执行Object result=pjp.proceed(pjp.getArgs());System.out.println(pjp.getSignature().getName()+"方法执行完毕了xxx执行结果是:"+result);return result;} catch (Throwable e) {System.out.println(pjp.getSignature().getName()+"方法被执行出错了xxx出现的异常是:"+e);throw new RuntimeException(e);} finally {System.out.println(pjp.getSignature().getName()+"方法不管有没有异常xxx都会执行的代码");}}
    }
    
  • 测试代码

    @Autowired
    private Calculator calculator; //最终注入时就是代理对象
    @Test //java的junit框架提供的注解
    public void test03(){System.out.println(calculator.getClass());calculator.add(1,0);//连接点
    }
    

运行测试代码,控制台输出add方法的日志增强代码:

经验分享:

Spring Aop应用的场景

日志记录,性能统计,安全控制,事务处理,异常处理等等。

利用AOP可以将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非主导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。

AOP与OOP区别

OOP(面向对象编程)针对业务处理过程的实体及其属性和行为进行抽象封装,以获得更加清晰高效的逻辑单元划分。

而AOP则是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。这两种设计思想在目标上有着本质的差异。

换而言之,OOD/OOP面向名词领域,AOP面向动词领域。

学习 spring中的aop要明确的事

	a 、开发阶段(我们做的):编写核心业务代码(开发主线):大部分程序员来做,要求熟悉业务需求。把公用代码抽取出来,制作成通知。(开发阶段最后再做):AOP 编程人员来做。在配置文件中,声明切入点与通知间的关系,即切面。:AOP 编程人员来做。b 、运行阶段(Spring  框架完成的):Spring 框架监控切入点方法的执行。一旦监控到切入点方法被运行,使用代理机制,动态创建目标对象的代理对象,根据通知类别,在代理对象的对应位置,将通知对应的功能织入,完成完整的代码逻辑运行。

7 spring AOP完成事务管理

引入案例:转账业务

需求:基于atm数据库的cardInfo表完成两个账户之间的转账业务

参考代码

  • CardInfoDao.java完成转账sql

    @Repository
    public class CardInfoDaoImpl implements CardInfoDao {@Autowiredprivate JdbcTemplate jdbcTemplate;@Overridepublic int updateIn(String cardId, BigDecimal inMoney) {return jdbcTemplate.update("UPDATE cardinfo SET balance=balance+? WHERE card_id=?",inMoney,cardId);}@Overridepublic int updateOut(String cardId, BigDecimal outMoney) {return jdbcTemplate.update("UPDATE cardinfo SET balance=balance-? WHERE card_id=?",outMoney,cardId);}
    }
    
  • CardInfoService.java完成转账业务

    @Service
    public class CardInfoServiceImpl implements CardInfoService {@Autowiredprivate CardInfoDao cardInfoDao;/*** @param outCardId 转出账户* @param inCardId 转入账户* @param money 交易金额*/@Overridepublic void transfer(String outCardId, String inCardId, BigDecimal money) {cardInfoDao.updateOut(outCardId,money);cardInfoDao.updateIn(inCardId,money);}
    }
    
  • 测试转账业务

    @RunWith(SpringJUnit4ClassRunner.class)  
    @ContextConfiguration(classes = SpringConfig.class)
    public class MySpringTester {@Autowiredprivate CardInfoService cardInfoService;@Testpublic void query() {cardInfoService.transfer("2394916393","2416932602",new BigDecimal(100));}
    }
    

    运行代码,两个账户金额发生变化:账户“2394916393”金额更新为900,账户“2416932602”金额更新为1100,转账成功!!
    我们尝试将CardInfoDao的sql故意写错试一试:

     @Overridepublic int updateIn(String cardId, BigDecimal inMoney) {return jdbcTemplate.update(//此处ST是故意写错的"UPDATE cardinfo ST balance=balance+? WHERE card_id=?",inMoney,cardId);}
    

    运行代码,两个账户金额依然发生变化:账户“2394916393”金额更新为800,账户“2416932602”金额却依然是1100,转账貌似有一个”成功了“,这种现象符合实际转账功能的需求么????当然不合理!!!转账是一定要保证:两个用户的钱同时变化的。所以转账业务有问题!怎么解决呢?依靠数据库的事务管理。

spring事务控制我们首先要认知到以下几个点:

第一:JavaEE 体系进行分层开发,事务处理位于业务层,Spring 提供了分层设计 业务层的事务处理解决方案。

第二:spring 框架为我们提供了一组事务控制的接口。具体在后面的第二小节介绍。这组接口是在spring-tx-xx.jar 中。

第三:spring 的事务控制都是基于 AOP 的,它既可以使用编程的方式实现,也可以使用配置的方式实现。我们学习的重点是使用配置的方式实现。

spring中事务管理机制依靠aop实现,那么完成事务管理也是遵循aop开发流程:首先我们需要定义事务管理的切面类,切面里面写什么代码呢?回忆之前自己管理事务,在核心业务代码基础上就是要提供事务提交、回滚相关的功能,

  • 事务切面类
    • commit
    • rollback
    • 。。。。

这个所谓的事务切面类,在spring中其实已经定义并提供了,称为事务管理器。

在转账案例中我们已经知道了spring中存在的事务问题,接下来我们使用aop技术让spring自动帮我们控制事务。

Spring 中事务控制的 API 介绍

  • PlatformTransactionManage:此接口是 spring 的事务管理器,它里面提供了我们常用的操作事务的方法,如下图:

因为PlatformTransactionManage是一个接口,并没有提供实际的方法实现。Spring为什么会抽取这样一个接口呢?有一个原因我们可以了解一下:

现下持久层框架众多,Spring没有办法提供一套事务的实现能够满足各大持久层框架的需求,比如MyBatis和Hibernate两大持久层框架,实现机制区别很大。所以spring的想法就是我把功能抽取出来,项目中结合自己实际使用的持久层来提供对应的代码实现:

案例:基于spring aop完成事务管理处理转账业务

分析:

我们现在的案例使用的持久层框架是spring内置的Spring-jdbc,所以事务切面类就应该根据上图指示,使用“DataSourceTransactionManager”。这个实现类spring-jdbc已经提供

我们要做的事情,就是让自己项目的spring容器可以扫描到这个事务管理类,但是因为这个类不是我们自己编写,无法直接添加@Component注解,只能在SpringConfig配置类中利用@Bean注入到spring容器中,详细代码如下所示:

  • pom.xml导入事务管理的依赖

    <dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId><version>5.2.25.RELEASE</version>
    </dependency>
    
  • SpringConfig配置类:配置DataSourceTransactionManager事务管理器对象,利用@EnableTransactionManagement开启事务管理

    @ComponentScan(basePackages = {"com.woniu.dao","com.woniu.service","com.woniu.controller","com.woniu.target","com.woniu.advance"}) //spring不管理实体类entity
    @PropertySource("classpath:db.properties")
    //开启spring AOP代理 proxyTargetClass默认值是false,就是JDK true启用cglib
    @EnableAspectJAutoProxy(proxyTargetClass = true) //开启spring aop动态代理
    @EnableTransactionManagement(proxyTargetClass = true)  //开启spring事务管理
    @Import({JdbcConfig.class}) //导入其他的配置类
    public class SpringConfig {@Beanpublic JdbcTemplate jdbcTemplate(HikariDataSource dataSource){JdbcTemplate jdbcTemplate=new JdbcTemplate();jdbcTemplate.setDataSource(dataSource);return jdbcTemplate;}/*** 事务管理器,即利用spring AOP管理事务时的增强类* @param dataSource* @return*/@Beanpublic DataSourceTransactionManager dataSourceTransactionManager(HikariDataSource dataSource){DataSourceTransactionManager dataSourceTransactionManager=new DataSourceTransactionManager();dataSourceTransactionManager.setDataSource(dataSource);return dataSourceTransactionManager;}
    }
    
  • 业务层哪个方法需要事务管理,添加spring提供事务注解@Transactional

    @Service
    public class CardInfoServiceImpl implements CardInfoService {@Autowiredprivate CardInfoDao cardInfoDao;//注解:spring提供注解@Transactional@Overridepublic void transfer(String inCardId, String outCardId, BigDecimal money) {cardInfoDao.updateOut(outCardId,money);cardInfoDao.updateIn(inCardId,money);}
    }
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/28051.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringMVC框架学习笔记(七):处理 json 和 HttpMessageConverter 以及文件的下载和上传

1 处理 JSON-ResponseBody 说明: 项目开发中&#xff0c;我们往往需要服务器返回的数据格式是按照 json 来返回的 下面通过一个案例来演示SpringMVC 是如何处理的 &#xff08;1&#xff09; 在web/WEB-INF/lib 目录下引入处理 json 需要的 jar 包&#xff0c;注意 spring5.x…

OpenCV练习(1)签名修复

1.目的 在学校的学习过程中&#xff0c;需要递交许多材料&#xff0c;且每份材料上都需要对应负责人签名&#xff0c;有时候找别人要签名&#xff0c;然后自己粘贴的话&#xff0c;会出现签名模糊&#xff0c;背景不是纯白透明。为此以word中的“颜色校正”功能为参照&#xf…

基于iBeacon蓝牙定位技术的反向寻车系统

随着城市化进程的加速和汽车保有量的不断增加&#xff0c;大型停车场成为了人们日常生活中不可或缺的一部分。然而&#xff0c;在繁忙的停车场中快速找到自己的车辆&#xff0c;成为了许多车主的难题。为了解决这一问题&#xff0c;维小帮基于iBeacon蓝牙技术打造的反向寻车系统…

Android开发AndroidStudio安装教程

本文图示展示AndroidStudio安装教程。 目录 一、下载安装包 二、安装 一、下载安装包 https://developer.android.google.cn/studio?hlzh-cn 二、安装 双击exe Next Next Next 默认点击Install Next 点击finish进入设置文件界面。 如果本地有设置文件&#xff0c;选择C…

推荐一款可以下载B站视频和音频的工具

cobalt是一个免费的下载网站&#xff0c;主要是用于载视频和音频。只要你把相应的网址复制下来&#xff0c;然后打开cobalt网站&#xff0c;黏贴网址&#xff0c;选择要下载的格式&#xff0c;就可以下载相应的音频或者视频了。 该网站非常简洁&#xff0c;使用也很简单。目前只…

【机器学习】Dify:AI智能体开发平台版本升级

一、引言 关于dify&#xff0c;之前力推过&#xff0c;大家可以跳转 AI智能体研发之路-工程篇&#xff08;二&#xff09;&#xff1a;Dify智能体开发平台一键部署了解&#xff0c;今天主要以dify为例&#xff0c;分享一下如何进行版本升级。 二、版本升级 2.1 原方案 #首次…

大模型与知识智能:心理疾病治疗的新希望

前言 随着社会的发展&#xff0c;心理疾病已成为一个日益突出的问题。据《柳叶刀》杂志的系统性综述显示&#xff0c;疫情之后&#xff0c;全世界抑郁症与焦虑症的患病率上升超过25%&#xff0c;其中青少年心理健康的影响最大。此外&#xff0c;2021年国内的精神障碍报告显示&…

光照药物稳定性试验箱百科

概念与作用 - 药品稳定性试验箱&#xff1a;一种精密设备&#xff0c;用于模拟药品在不同环境条件下的存储情况。 - 环境模拟&#xff1a;通过控制温度、湿度等参数&#xff0c;复制各种实际储存条件&#xff0c;以测试药品稳定性。 - 保障药品质量&#xff1a;通过试验&…

Kafka 如何保证消息顺序及其实现示例

Kafka 如何保证消息顺序及其实现示例 Kafka 保证消息顺序的机制主要依赖于分区&#xff08;Partition&#xff09;的概念。在 Kafka 中&#xff0c;消息的顺序保证是以分区为单位的。下面是 Kafka 如何保证消息顺序的详细解释&#xff1a; ⭕分区内消息顺序 顺序写入&#…

windows 共享给linux 的使用方法

windows 作为服务器&#xff0c;linux作为客户端进行文件共享&#xff0c;有3种方法&#xff1a;samba nfs&#xff08;网络硬盘&#xff09;虚拟机共享&#xff08;VirtualBox vboxsf&#xff09;。 Samba 共享&#xff1a; 打开【控制面板】-->【启动或关闭windows功能】…

Apache Tomcat介绍

目录 前言 一、Apache Tomcat的历史 二、核心特性与组件 三、Tomcat-基本使用 总结 前言 在Java Web开发领域&#xff0c;Apache Tomcat是一个不可或缺的核心组件。作为一个轻量级的开源Web应用服务器&#xff0c;Tomcat提供了一种简单而高效的方式来部署和管理Java Servle…

MySQL 使用 MyFlash 快速恢复误删除、误修改数据

一、MyFlash MyFlash 是由美团点评公司技术工程部开发并维护的一个开源工具&#xff0c;主要用于MySQL数据库的DML操作的回滚。这个工具通过解析binlog日志&#xff0c;帮助用户高效、方便地进行数据恢复。MyFlash的优势在于它提供了更多的过滤选项&#xff0c;使得回滚操作变…

论文阅读笔记:Towards Higher Ranks via Adversarial Weight Pruning

论文阅读笔记&#xff1a;Towards Higher Ranks via Adversarial Weight Pruning 1 背景2 创新点3 方法4 模块4.1 问题表述4.2 分析高稀疏度下的权重剪枝4.3 通过SVD进行低秩逼近4.4 保持秩的对抗优化4.5 渐进式剪枝框架 5 效果5.1 和SOTA方法对比5.2 消融实验5.3 开销分析 6 结…

gitLab批量下载有权限的项目

前言 参考 https://www.jianshu.com/p/b3d4e5cee835 适用于git私服拉取个人所涉及权限的代码&#xff0c;方便有多个项目权限的人快速拉取自己所有权限的代码。 默认生成目录结构与gitlab一致 步骤一:获取权限你的代码权限文件d 从gitlab私服生成所有你有权限的代码信息 …

模型 WOOP

说明&#xff1a;系列文章 分享 模型&#xff0c;了解更多&#x1f449; 模型_思维模型目录。不再拖延和懒惰&#xff0c;让梦想照进现实。 1 WOOP模型的应用 1.1 WOOP模型提高自己健身习惯 如果你想要养成健身的习惯&#xff0c;那么使用WOOP模型来提高自己健身习惯&#xf…

全光万兆时代来临:信而泰如何推动F5G-A(50PONFTTR)技术发展

技术背景 F5G-A&#xff08;Fifth Generation Fixed Network-Advanced&#xff0c;第五代固定网络接入&#xff09;是固定网络技术的一次重大升级&#xff0c;代表了光纤网络技术的最新发展。F5G-A旨在提供更高的带宽、更低的延迟、更可靠的连接以及更广泛的应用场景。 F5G-A六…

【多线程】如何使用jconsole工具查看Java线程的详细信息?

&#x1f970;&#x1f970;&#x1f970;来都来了&#xff0c;不妨点个关注叭&#xff01; &#x1f449;博客主页&#xff1a;欢迎各位大佬!&#x1f448; 文章目录 1. 先运行java程序&#xff01;2. 在jdk目录下的bin文件夹中找到jconsole.exe3. 新建连接4. 观察线程状态5. …

OpenCV形态学

什么事形态学处理 基于图像形态进行处理的一些基本方法&#xff1b; 这些处理方法基本是对二进制图像进行处理&#xff1b; 卷积核决定着图像出来后的效果。 一 图像二值化 什么是二值化 将图像的每个像素变成两种值&#xff0c;如0,255. 全局二值化。 局部二值化。 thres…

08 SpringBoot 自定定义配置

SpringBoot自定义配置有三种方式&#xff1a; 使用PropertySource进行自定义配置 使用ImportResource进行自定义配置 使用Configuration进行自定义配置 PropertySource ​ 如果将所有的配置都集中到 application.properties 或 application.yml 中&#xff0c;那么这个配置文…

解决javadoc一直找不到路径的问题

解决javadoc一直找不到路径的问题 出现以上问题就是我们在下载jdk的时候一些运行程序安装在C:\Program Files\Common Files\Oracle\Java\javapath下&#xff1a; 一开始是没有javadoc.exe文件的&#xff0c;我们只需要从jdk的bin目录下找到复制到这个里面&#xff0c;就可以使用…