spring (Aop) day 1024

ok了家人们,继续学习spring ,这段知识点有点绕,建议搭配b站的视频去学,passion!!!

.AOP-面向切面编程

8.1 动态代理

8.1.1 概述
什么是代理?在现实生活中,代理很常见。比如,我们需要去
某个地方,需要自己开车过去,但是公交车师傅的出现替代了
我们自己开车的这个步骤,我们只需要乘坐公交车就可以到达
我们需要到达的目的地。这就是一种代理方式。
用自己的话总结一下:代理就是原本需要自己去完成的工作可
以由一个新的替代者来完成,这就是代理的一种表现。 在
Java 中就是在不侵入原来代码的情况下完成功能的增强。
Java 中常见代理分类:静态代理,基于 JDK 的动态代理,基于
CGlib 的动态代理
8.1.2 静态代理
举个例子:现实中明星都是有经纪人的,经纪人的作用就是帮
明星来处理业务,节目组要找明星来表演,那么肯定不是和明
星直接联系的,而是明星的经纪人出面和节目组洽谈,而且只
有当业务条件满足时,明星才会出面表演,那么这个经纪人就
是明星的代理人,他可以帮助明星来筛选演出业务,条件达不
到要求的表演就过滤了,只有达到要求了,才会被经纪人接收
然后明星就会出场表演,也就是拦截了外界对明星的直接访
} 问。这也是 JAVA 中代理对象的作用,产生一个代理对象用来
拦截外界对真实业务的访问。
可以看出,经纪人会将外界给明星的信息进行拦截、处理,这
就是我们常说的代理模式。
静态代理的实现方式
  • 经纪人和明星在一些行为上有共同点,共同的目标,所以
    定义一个共有接口: start 接口 ( 参加节目 )
  • 明星实现接口的行为,因为真正出力的是明星。
  • 经纪人要代表明星,就需要和明星有同样的行为,同时持
    有明星的引用 ( 经纪人能找到明星 )
  • 调用方要找明星之前,先找到经纪人。由经纪人出面进行
    谈判,比如参加节目前片酬,比如参加节目后发的微博。
     

静态代理的代码实现

  • 接口 
public interface FindWife {public void findWife(String message);
}
  •  代理类
public class BuyHouseProxy implements BuyHouse{
//定义一个 有买房需求的
private BuyHouse buyHouse;
//在创建代理对象的时候 得有委托人
public BuyHouseProxy(BuyHouse buyHouse) {this.buyHouse = buyHouse;
}@Overridepublic void buyHouse() {//代理人 帮助 委托人System.out.println("我是中介,帮您买房,先付款...");buyHouse.buyHouse();//最终 委托人买方法System.out.println("将信息偷偷滴卖给装修的人...");}
}
  • 代理类
package com.cjx.service;
//买房的中介 代理
public class BuyHouseProxy implements BuyHouse{//定义一个 有买房需求的private BuyHouse buyHouse;public BuyHouseProxy(BuyHouse buyHouse) {this.buyHouse = buyHouse;}@Overridepublic void buyHouse() {//代理人 帮助 委托人System.out.println("我是中介,帮您买房,先付款...");buyHouse.buyHouse();//最终 委托人买方法System.out.println("将信息偷偷滴卖给装修的人...");}
}
package com.cjx.service;
//婚介中心
public class FindWifeProxy implements FindWife{//定义一个 有找媳妇需求的人private FindWife findWife;public FindWifeProxy(FindWife findWife) {this.findWife = findWife;}@Overridepublic void findWife(String message) {System.out.println("我们这里是百合网,交会员费,提供优质服务,按照您的条件找");findWife.findWife(message);System.out.println("祝你幸福...");System.out.println("又把信息卖给了婚纱摄影");}
}
  • 被代理类
package com.cjx.service;
//消费者 委托人
public class Customer implements BuyHouse,FindWife{@Overridepublic void buyHouse() {System.out.println("看房源...");System.out.println("谈价格...");System.out.println("过户...");}@Overridepublic void findWife(String message) {System.out.println("要求是:"+message);System.out.println("主要是暖被窝...");}
}
  • 测试
package com.cjx.test;import com.cjx.service.*;
import org.junit.Test;public class DemoTest {@Testpublic void test01(){//没有代理的时候 自己买方房Customer customer = new Customer();customer.buyHouse();customer.findWife("xx");System.out.println("-------------------");//找中介 代理人BuyHouseProxy buyHouseProxy = new BuyHouseProxy(customer);buyHouseProxy.buyHouse();System.out.println("-------------------");//找媳妇 代理人FindWifeProxy findWifeProxy = new FindWifeProxy(customer);findWifeProxy.findWife("迪丽热巴..。");System.out.println("-------------------");//      动态代理BuyHouse proxy = (BuyHouse) JDKProxy.getProxy(customer);proxy.buyHouse();}
}
从实现上可以看到 代理 的主要作用是 方法增强,它可以在不
惊动 被代理类的情况下修改被代理类的行为。这有助于系统
解耦。我们这里代理类和被代理类都是自己亲自敲好的,即在
程序运行前代理类的 .class 文件就已经存在了的形式叫做静态
代理。值得注意的是,代理类和被代理类应该共同实现一个接
口,或者是共同继承某个类。
静态代理的缺点
  • 我们需要在运行前手动创建代理类,这意味着如果有很多
    代理的话会很繁琐,一个被代理就需要一个代理;
  • 其次代理类 和 被代理类 必须实现同样的接口,万一接口
    有变动,代理、被代理类都得修改,容易出问题;
8.1.3 动态代理
动态代理 与 静态代理 最大的区别就是不用我们创建那么多
类,敲那么多代码。在程序运行时,运用反射机制动态创建而
成。
JDK 中为我们提供了 Proxy 类来实现动态代理,其中最重要的
方法是 Proxy.newProxyInstance :只需要我们传入相关信
息,它就可以返回我们需要的代理对象。
Object obj = Proxy.newProxyInstance(ClassLoader
loader,Class<?>[] interfaces, InvocationHandler h)
上面的方法可以实现动态的拦截被代理类的方法,也就是说我
们无需定义代理类,由该方法自动产生可以实现代理的对象。
package com.cjx.service;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;public class JDKProxy {//获取代理对象的方法 参数:被代理对象 委托人
//传入被代理人 返回一个代理对象public static Object getProxy(Object obj) {Object proxy = null;proxy = Proxy.newProxyInstance(obj.getClass().getClassLoader(),
//类加载器,将生成的代理类加载到内存中obj.getClass().getInterfaces(),
// 生成的代理类需要实现的接口的字节码
//invoke:此invoke方法并非是反射的invoke方法,此方法属于动态代理,
//调用代理类的哪个方法,invoke就表示那个方法new InvocationHandler() {/*proxy:代理对象method:委托人需要增强的方法args:要实现功能的参数Object:被增强方法的返回值*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throwsThrowable {Object result = null;
//这个方法来自哪个接口定义的方法Class<?> clazz =method.getDeclaringClass();if (clazz ==BuyHouse.class) {
//我们应该根据委托人不同的需求,执行不同的功能增强String methodName =method.getName();if(methodName.equalsIgnoreCase("buyHouse")) {
//对买房的操作进行增强System.out.println("我是中介,帮您买房,先付款...");result =method.invoke(obj, args);System.out.println("将信息偷偷滴卖给装修的人...");}}if (clazz == FindWife.class) {//我们应该根据委托人不同的需求,执行不同的功能增强String methodName = method.getName();if (methodName.equalsIgnoreCase("findWife")) {System.out.println("我们这里是百合网,交会员费,提供优质服务,按照您的条件找");result = method.invoke(obj, args);System.out.println("又把信息卖给了婚纱摄影");}}return result;}});return proxy;}}
明星与经纪人的关系介绍了静态代理,不好之处在于一个经纪
人只能代理一个明星,一旦明星有变动,或者想要代理其他明
星时,需要修改、创建经纪人,大量使用这种静态代理,会使
我们系统内的类的规模增大,并且不易维护;
而动态代理模式,大大减少类的创建、修改成本。此外动态代
理还符合 AOP ( 面向切面编程 ) 思想,在很多场合都有使用。
通过讲解可以得出结论 : 代理模式主要用于扩展原功能又不侵
入(修改)源代码。 ( 增强功能 )
8.1.4 cglib代理
JDK 的动态代理已经很好的帮我们完成了代理工作,那么,
CGlib 动态代理又有什么好用的特征呢?
我们可以看出,静态代理和基于 JDK 的动态代理的被代理类都
需要实现接口,那么,如果我的类没有实现接口,但是,我想
给它配置代理,那么,应该怎么实现呢?
这时候,就轮到 CGlib 出场了, CGlib 可以代理没有接口的类。
我们需要在 pom 文件中引入 CGlib jar 包。
<!--https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.9</version>
</dependency>
cglib 动态代理其实就是把原有对象传进去进行方法拦截,拦
截到之后进行逻辑增强。
8.1.5 代理总结
使用代理技术就是为了帮我们在不入侵原有代码的情况下增强
业务逻辑!
你完全可以使用静态代理一个一个去定义代理类,但是这样的
话太过于繁琐,而且有些情况下你不知道未来会有什么接口
(比如咱们的 Mybatis ,你现在有个 UserMapper.java ,以后
还可能有更多其他的 Mapper 接口,这些都是不确定的),所
以就是用动态代理去给他们生成代理对象吧
有接口就用 JDK 动态代理,没有接口就用 CGLIB 动态代理

8.2 AOP概述

OP Aspect Oriented Programming 的缩写,意为:面向切
面编程,通过 运行期动态 实现程序功能的统一维护的一种技
术。 AOP OOP 的延续,是软件开发中的一个热点,也是
Spring 框架中的一个重要内容。
AOP 弥补了 OOP 的不足,基于 OOP 基础上进行横向开发;
OOP 程序开发以类为主题模型,一切围绕对象进行,通过构
建模型来完成任务; AOP 程序的开发主要关注 OOP 开发中的
共性功能,一切围绕共性功能进行。
AOP 通过采取横向抽取机制,已经完全取代了传统纵向继承体
系重复性代码的编写方式
AOP 的底层封装了动态代理,我们可以理解为 AOP 是动态代理
的一种简单写法,进行功能的增强!
简单理解: AOP 就是实现业务代码和逻辑代码的解耦,但在运
行时又可以织入在一起。
场景 名称
场景描述
事务控制
批量的为业务对象,增加事务处理的功能,不用
每个对象都去做事务处理
记录跟踪
批量的为业务对象,增加日志记录的功能,不用
在每个方法执行进行日志记录
权限控制
批量的为业务对象,增加权限检查,不用每个业
务对象都做安全检查
异常处理
批量的为业务对象,增加异常情况的处理功能,
不用在每个方法执行进行异常处理
参数校验
批量的为业务对象,增加各种入参的检查,不用
在方法内部进行检
等等
.....

8.3 AOP 相关概念

  • Joinpoint( 连接点 ) : 所谓连接点是指那些被拦截到的点。
    spring , 这些点指的是方法 , 因为 spring 只支持方法类型
    的连接点。
  • Pointcut( 切入点 ) : 所谓切入点是指我们要对哪些 Joinpoint
    进行拦截的定义。例如:我们配置 save 方法就是切入点
  • Advice( 通知 / 增强 ) : 所谓通知是指拦截到 Joinpoint 之后所
    要做的事情就是通知。 通知的类型:前置通知 , 后置通知 ,
    常通知 , 最终通知 , 环绕通知。 例如: @Before 前置通知 :
    切入点运行前执行。
  • Target( 目标对象 ) : 代理的目标对象。举例:
    UserServiceImpl ,他就是目标对象,因为它里面的功能需
    要被增强。
     
  • Weaving( 织入 ) : 就是代码运行的时候 业务代码和逻辑代码
    织入到一起执行。例如:把 before 方法在 save 方法执行之
    前执行了这就是织入。
  • Aspect( 切面 ) : 是切入点和通知的结合。切面 = 切入点 + 方位
    信息 + 增强逻辑,例如: AopAdvice 类 是一个切面类
     
  •  Proxy(代理): 一个类被AOP织入增强后,就产生一个结果
    代理类。例如: AccountServiceImpl 它的功能在增强的时
    候,实际是生成了代理对象增强的。

8.4 AOP案例

8.4.1 需求分析
需求:任意业务层接口执行前后获取当前系统时间
分析:
  • 原始程序中将共性功能抽取出来独立制作成方法放在特定类中
  • 定义带有共性功能的方法名
  • 将抽取出来的共性功能与对应的方法名之间绑定关系
8.4.2 环境准备
  • 实体类
package com.cjx.pojo;import org.springframework.stereotype.Component;@Component
public class User {private int id;private String name;//省略get set方法
}
  • 配置类
package com.cjx.config;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;//Spring配置文件
@Configuration
@ComponentScan("com.cjx")
@EnableAspectJAutoProxy
public class SpringConfig {
}
  • 通知类
public class AopAdvice {
public void before(){
System.out.println("当前方法执行前初始时间毫
秒值是:"+System.currentTimeMillis());
}
public void after(){
System.out.println("当前方法执行后初始时间毫
秒值是:"+System.currentTimeMillis());
}
}
  • 业务层接口和实现类
package com.cjx.service;import com.cjx.pojo.User;
import org.springframework.stereotype.Service;import java.util.List;@Service
public class UserServiceImpl implements UserService{@Overridepublic void save(User user) {//System.out.println("当前方法执行前初始时间毫秒值是:"+System.currentTimeMillis());System.out.println("保存了用户数据~");//System.out.println("当前方法执行后初始时间毫秒值是:"+System.currentTimeMillis());}@Overridepublic void update(User user) {//System.out.println("当前方法执行前初始时间毫秒值是:"+System.currentTimeMillis());System.out.println("更新了用户数据~");//System.out.println("当前方法执行后初始时间毫秒值是:"+System.currentTimeMillis());}@Overridepublic void delete(String id) {System.out.println("删除了用户数据~");}@Overridepublic List<User> findAll() {System.out.println("查询了用户数据~");return null;}
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes =
{SpringConfig.class})
public class DemoTest {
@Autowired
private UserService userService;
@Test
public void test01(){
userService.save(new User());
}
}
8.4.3 AOP实现
  • 导入aspect坐标
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springaspects</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
  • 将共性功能抽取出来制作成独立的通知方法写入通知类
    中。创建一个新的类,将共性功能提取出来制作成独立的
    方法
/*
通知类
*/
public class AopAdvice {public void before(){System.out.println("当前方法执行前初始时间毫秒值是:"+System.currentTimeMillis());}public void after(){System.out.println("当前方法执行后初始时间毫秒值是:"+System.currentTimeMillis());}
}
  • 将共性功能抽取的位置定义成切入点,写入通知类中
/*
通知类
切入点:@Pointcut
你想增强哪个方法,那个方法就当做切入点,切入点在通知
类中这样配置
void
com.lzw.service.UserServiceImpl.save(com.lzw.poj
o.User)
*/
public class AopAdvice {
//配置切入点 是用来找到需要被增强的方法的@Pointcut("execution(voidcom.lzw.service.UserServiceImpl.save(com.lzw.pojo.User))")public void pt(){}
}
  • 绑定原始操作与被抽取的功能之间的关系
package com.cjx.aop;import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;import java.util.Date;/*
通知类切入点:@Pointcut你想增强哪个方法,那个方法就当做切入点,切入点在通知类中这样配置
void
com.lzw.service.UserServiceImpl.
save(com.lzw.pojo.User)
@Component 我这个通知类交给spring管理
@Aspect 当前类为切面类 里面包含 切入点+方位信息
+增强逻辑 目的是spring底层自动完成织入
*/
@Component
@Aspect
public class AopAdvice {/*before after 使我们抽出来的 逻辑代码在aop的术语中 这两个方法 叫做通知方法在 pt 切入点 方法执行之前 执行 before功能*///配置切入点 是用来找到需要被增强的方法的@Pointcut("execution(void com.cjx.service.UserServiceImpl.save(com.cjx.pojo.User))")public void pt(){}@Pointcut("execution(void com.cjx.service.UserServiceImpl.update(com.cjx.pojo.User))")public void update(){}@Before("pt()")public void before(){System.out.println("当前方法执行前初始时间毫秒值是:"+System.currentTimeMillis());}@After("pt()")public void after(){System.out.println("当前方法执行后初始时间毫秒值是:"+System.currentTimeMillis());}@Before("update()")public void before01(){System.out.println("当前方法执行的时间是:"+new Date());}@After("update()")public void after01(){System.out.println("当前方法执行的时间是:"+new Date());}
}
  • Spring配置类上声明开启AOP功能
package com.cjx.config;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;//Spring配置文件
@Configuration
@ComponentScan("com.cjx")
@EnableAspectJAutoProxy
public class SpringConfig {
}
8.4.4 工作流程分析
  • Spring容器启动,加载bean
  • 启动AOP,加载所有的切入点
  • bean 工作的过程中, AOP 内部监听机制一直监听配置的切
    入点是否运行
  • 当切入点对应的对象(目标对象)执行对应的切入点方法
    时,创建目标对象的代理对象
  • 动态将通知内容织入到代理对象对应的方法中
  • 最终由代理对象完成最终工作
package com.cjx.test;import com.cjx.config.SpringConfig;
import com.cjx.pojo.User;
import com.cjx.service.UserService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import java.sql.PreparedStatement;@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class UserTest {@Autowiredprivate User user;@Autowiredprivate UserService userService;@Testpublic void test01(){userService.save(user);userService.update(user);userService.delete("1");userService.findAll();}
}

ok了家人们,see you later

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

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

相关文章

学习虚幻C++开发日志——TSet

TSet 官方文档&#xff1a;虚幻引擎中的Set容器 | 虚幻引擎 5.5 文档 | Epic Developer Community (epicgames.com) TSet 是通过对元素求值的可覆盖函数&#xff0c;使用数据值本身作为键&#xff0c;而不是将数据值与独立的键相关联。 默认情况下&#xff0c;TSet 不支持重…

iOS 18.2开发者预览版 Beta 1版本发布,欧盟允许卸载应用商店

苹果今天为开发人员推送了iOS 18.2开发者预览版 Beta 1版本 更新&#xff08;内部版本号&#xff1a;22C5109p&#xff09;&#xff0c;本次更新距离上次发布 Beta / RC 间隔 2 天。该版本仅适用于支持Apple Intelligence的设备&#xff0c;包括iPhone 15 Pro系列和iPhone 16系…

【设计模式系列】观察者模式

一、什么是观察者模式 观察者模式&#xff08;Observer Pattern&#xff09;是一种行为设计模式&#xff0c;它定义了对象之间的一对多依赖关系&#xff0c;当一个对象的状态发生变化时&#xff0c;所有依赖于它的对象都会得到通知并自动更新。这种模式也被称为发布-订阅模式&…

「重磅」中国电信数据湖+数据中台实施方案(附60页方案)

来源:公众号-数据分析小兵 作者按 哈喽,大家好,我是数据分析小兵,今天小兵向大家分享中国电信基于数据湖的数据中台实施方案。 方案核心内容一:数据湖的搭建与实施 数据湖是一套针对海量多源异构数据,具备数据采集、数据存储、数据计算、数据访问、数据管理的技术架构…

1.CentOS安装

CentOS安装 新建虚拟机 选择安装方式 指定镜像方式 选择操作系统类型 设置虚拟机名称和位置 指定磁盘大小 点击“自定义硬件” 指定内存大小 指定镜像位置 点击“开启此虚拟机” 选择“Install CentOS 7”并回车 选择语言 选择安装“GNOME桌面”环境 配置安装位置 配置网络和…

springboot高校科研项目和课题管理平台-计算机毕业设计源码18198

摘要 随着科技的快速发展和高校科研水平的持续提高&#xff0c;科研项目和课题的管理逐渐变得复杂多样。传统的管理方式&#xff0c;如使用纸质文档或简单的电子表格进行记录&#xff0c;已经无法满足现代高校科研管理的需求。这不仅影响了科研工作的效率&#xff0c;还可能导致…

CentOS 7(Linux)详细安装教程

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 一、CentOS镜像的下载&#xff08;准备工作&#xff09; 我选择的是其他镜像源的下载地址&#xff1a; Index of /centos-vault/7.6.1810/isos/x86_64/ | 南阳理工学院开源镜…

8个方法教会你提高企业培训效率

培训成本是企业中的一个复杂问题。它完全取决于课程内容、培训方法以及成本效益。在计算培训费用时&#xff0c;公司会面临许多关于包括哪些内容、如何进行以及假设情景的问题。 企业员工培训的每个方面都会产生自己的成本。例如&#xff1a; 地点&#xff1a;我们专门找个培训…

冒泡排序(Python)

冒泡排序&#xff1a;依次比较相邻的两个数&#xff0c;将大数放在后面&#xff0c;小数放在前面。 n个数排序共需进行n-1趟&#xff0c;第一趟排序结束时&#xff0c;最后一个元素为所有元素中的最大值。 冒泡排序的原理 1&#xff09;比较相邻元素&#xff1a;如果第一个比…

婚纱相册必须去摄影店吗?其实自己会拍照就能实现,性价比更高

一直以来&#xff0c;婚纱照都是新人们婚礼筹备中不可或缺的部分。然而&#xff0c;高昂的摄影店价格让不少新人望而却步。其实&#xff0c;只要掌握一些拍照技巧&#xff0c;自己在家就能制作出独一无二的婚纱相册&#xff0c;不仅性价比超高&#xff0c;还能留下更多珍贵的回…

Android 中的串口开发

一&#xff1a;背景 本文着重讲安卓下的串口。 由于开源的Android在各种智能设备上的使用越来越多&#xff0c;如车载系统等。在我们的认识中&#xff0c;Android OS的物理接口一般只有usb host接口和耳机接口&#xff0c;但其实安卓支持各种各样的工业接口&#xff0c;如HDM…

条码检测系统——基于MATLAB的一维条码识别

摘 要&#xff1a;条码技术是如今应用最广泛的识别和输入技术之一&#xff0c;由于其包含的信息量大&#xff0c;识别错误率低而在各个方面得到很大的重视。它发展迅速并被广泛应用于于工业、商业、图书出版、医疗卫生等各行各业。由我国目前发展现状来看&#xff0c;条码的正…

攻坚金融关键业务系统,OceanBase亮相2024金融科技大会

10月15-16日&#xff0c;第六届中新数字金融应用博览会与2024金融科技大会&#xff08;简称“金博会”&#xff09;在苏州工业园区联合举办。此次大会融合了国家级重要金融科技资源——“中国金融科技大会”&#xff0c;围绕“赋能金融高质量发展&#xff0c;金融科技创新前行”…

【C++指南】运算符重载详解

引言 C 提供了运算符重载这一特性&#xff0c;允许程序员为自定义类型&#xff08;如类和结构体&#xff09;定义运算符的行为。 通过运算符重载&#xff0c;可以使自定义类型对象像内置类型一样使用运算符&#xff0c;从而提高代码的可读性和易用性。 本文将详细介绍 C 中运算…

【状态机DP】力扣2786. 访问数组中的位置使分数最大

给你一个下标从 0 开始的整数数组 nums 和一个正整数 x 。 你 一开始 在数组的位置 0 处&#xff0c;你可以按照下述规则访问数组中的其他位置&#xff1a; 如果你当前在位置 i &#xff0c;那么你可以移动到满足 i < j 的 任意 位置 j 。 对于你访问的位置 i &#xff0c…

若依微服务15 - RuoYi-Vue3 实现前端独立运行

正文开始&#xff1a; RuoYi-Vue3 使用 Vue3 Element Plus Vite 技术栈。 GitHub 开源地址&#xff1a;https://github.com/yangzongzhuan/RuoYi-Vue3 本文介绍使用若依提供的在线后端接口&#xff0c;仅启动前端项目并进行界面开发&#xff0c;而无需启动后端服务。 一、克隆…

AI视听新体验!浙大阿里提出视频到音乐生成模型MuVi:可解决语义对齐和节奏同步问题

MuVi旨在解决视频到音乐生成(V2M)中的语义对齐和节奏同步问题。 MuVi通过专门设计的视觉适配器分析视频内容,以提取上下文 和时间相关的特征,这些特征用于生成与视频的情感、主题及其节奏和节拍相匹配的音乐。MuVi在音频质量和时间同步方面表现优于现有基线方法,并展示了其在风…

C++:模板的特化与分离编译

之前我们在介绍模板的时候仅仅是简单的介绍了模板的用法&#xff0c;本篇文章我们来详细的介绍下模板中比较重要的几个点。 一&#xff0c;非类型模板参数 我们之前的c中&#xff0c;会将经常使用的而又确保在我们程序的运行过程中值不会改变的值进行#define&#xff1a; #d…

初入编程之路,启航代码海

#1024程序员节|征文# 前言 今天又是1024程序员节了&#xff0c;第一次听说这个节日是在我在23年刚刚上大一的时候听学长他们说的&#xff0c;如今已经是24年了&#xff0c;虽然只学习了一年的编程但我已经了解到了这条路上的不易。希望能够在这条路上面一路坚持下去&#xff0…

力扣_斐波那契数列

本题目本质和爬楼梯是一样的&#xff0c;主要运用的是递归来解题。 class Solution:my_dict {}def fib(self, n: int) -> int:if self.my_dict.get(n) is not None: # 先判断有没有计算过这个值return self.my_dict.get(n)tempResult 0if n > 2:tempResult self.fib…