Java框架学习(三)spring5高级49讲

文章目录

  • 1、BeanFactory与ApplicationContext
  • 2、BeanFactory与ApplicationContext的容器实现
    • BeanFactory的容器实现
      • 后处理器排序
    • ApplicationContext的容器实现
  • 3、Bean的生命周期
    • Bean后处理器
  • 4、常见的Bean后处理器
  • 5、常见BeanFactory后处理器
  • 6、Aware和InitializingBean接口
  • 7、初始化与销毁阶段的回调
  • 8、Bean的作用域scope
    • scope失效
  • 9、基于AJC编译器实现AOP
  • 10、基于agent类加载实现AOP
  • 11、基于JDK动态代理 / CGLIB动态代理 实现AOP
  • 12、JDK动态代理实现原理
  • 13、CGLib动态代理实现原理
  • 14、MethodProxy
    • CGLIB和JDK动态代理的实现区别
  • 15、Spring AOP与选择代理
    • AOP核心概念
      • 通知(Advice)类型
      • @Order控制通知顺序
      • 切入点表达式(Pointcut)与@PointCut
      • 连接点(JoinPoint)
    • 基于代码实现的AOP
    • Spring对于代理的选择规则
  • 16、切入点匹配
  • 17、从@Aspect到@Advisor
  • 18、通知的执行
    • 基于适配器模式将所有通知转为环绕通知
    • 基于责任链模式实现通知的执行
  • 19、动态通知调用
  • 47、@Autowired底层

1、BeanFactory与ApplicationContext

BeanFactory负责:

  • 创建、管理和配置应用程序中的对象(Bean)
  • 实现IoC(控制反转)和DI(依赖注入)
  • 是spring的核心机制。

ApplicationContext是BeanFactory的子接口。与BeanFactory相比,ApplicationContext组合了另外四个接口功能,使其可以支持:

  • 国际化(MessageSource,多语言支持)
  • 资源解析加载(ResourcePatternResolver,根据通配符匹配资源名加载资源)
  • 获取环境配置信息(EnvironmentCapable,根据配置的环境参数加载不同的配置文件,从而实现在不同环境下的灵活配置和适配。)
  • 事件发布功能(ApplicationEventPublisher,允许应用程序中的Bean发送事件。同时,其他Bean可以监听这些事件,使用@EventListener注解,并在事件发生时采取相应的处理措施。这为应用程序的解耦和模块间通信提供了便利的机制)。

在这里插入图片描述

在这里插入图片描述

2、BeanFactory与ApplicationContext的容器实现

BeanFactory的容器实现

1、创建BeanFactory的实现类对象。
2、定义bean(类型、scope等),并注册到BeanFactory
3、注册常用的后处理器。(解析注解,注入等)

在这里插入图片描述
在这里插入图片描述

BeanFactory不会做的事:

  • 不会主动添加Bean后处理器
  • 不会主动调用Bean的后处理器来解析注解
  • 不会主动初始化单例
  • 不会解析 $#

可以看出BeanFactory实现的是容器的基本功能,而下边要讲的ApplicationContext的容器实现,则会将上边的功能一一实现。

后处理器排序

Bean的后处理器有很多,用来解析不同的注解,比如@Autowired@Resource等,处理器有其固定的执行的顺序,当然也可通过添加比较器的方式来改变。

@Autowired@Resource同时出现时,执行结果与Bean后处理器执行顺序有关。
在这里插入图片描述

ApplicationContext的容器实现

Spring中的ApplicationContext是用于管理Bean的高级容器,提供了多种实现方式来适应不同场景和需求。其中常见的四种实现方式分别是:

1、ClassPathXmlApplicationContext:通过类路径下的XML配置文件加载和管理Bean。

2、FileSystemXmlApplicationContext:通过文件系统路径加载XML配置文件来管理Bean。

3、AnnotationConfigApplicationContext:基于Java注解的实现方式,使用@Configuration和@Bean注解配置Bean。

4、WebApplicationContext:用于Web应用,加载Web相关的配置信息。

1、2都是基于XML文件配置来构建容器内容,1是通过加载XML文件资源读取,2是直接XML文件路径读取。

3、4都是基于@Configuration和@Bean注解配置,不同的是第4种方式集成了TomcatServer,配置了与网页请求处理相关的Bean,主要包括:ServletWebServerFactory、Servlet分发、Servlet请求分发注册,以及相应请求路径的控制器Bean。
在这里插入图片描述

3、Bean的生命周期

Bean主要是生命周期包括:

  • 1、实例化。
  • 2、依赖注入:@Autowired
  • 3、初始化:@PostConstruct
  • 4、销毁:@PreDestroy

在这里插入图片描述

Bean后处理器

除了基本的4个生命周期,还可以通过添加Bean后处理器,定位到更加精细的生命周期阶段,以便进行功能的增强,比如:

  • 实例化执行之前、实例化执行之后
  • 依赖注入之前(@Autowired、@Resource、@Value)
  • 初始化之前、初始化之后
  • 销毁执行之前

在这里插入图片描述
在这里插入图片描述

4、常见的Bean后处理器

  • 1、common注解后处理器:解析 @Resourse、@PostConstruct、@PreDestroy
  • 2、autowired注解处理器:解析@Autowired、@Value

在这里插入图片描述
从上边结果看到,common后处理器的执行优先级更高。

  • ConfigurationPropertiesBindingPostProcessor:解析@ConfigurationProperties

在这里插入图片描述

5、常见BeanFactory后处理器

  • ConfigurationClassPostProcessor:主要职责就是解析@Configuration注解的类,识别其中的@Bean方法,还可以解析@ComponentScan、@Import、@ImportResource
  • MapperScannerConfigurer:解析@Mapper,对应mybatis的MapperScan注解。

6、Aware和InitializingBean接口

Aware接口是一组特殊的接口,它们允许Bean感知或获取容器的某些方面或上下文信息。通过实现Aware接口,Bean可以与Spring容器进行交互,并获取一些有用的信息或执行特定的操作。
在这里插入图片描述
使用InitializingBean接口可以实现Bean的初始化逻辑。

Aware和InitializingBean接口实现的功能,使用Bean后处理器也可以实现,但Aware和InitializingBean是内置接口功能,不依赖外部,是一种内聚的使用方法,而后处理的方法是分模块解耦的,如果其他模块失效,则后处理器的执行也可能失效。

7、初始化与销毁阶段的回调

指定初始化的方法有3种:

  • 1、通过后处理器的@PostConstruct
  • 2、通过 InitializingBean内置的接口
  • 3、通过在@Bean注解时,指定参数
    在这里插入图片描述
    在这里插入图片描述

执行的优先级:
在这里插入图片描述

销毁的方式与初始化类似也有3种:
在这里插入图片描述

8、Bean的作用域scope

Spring提供了以下几种常见的Bean作用域:

  • Singleton(单例):在整个应用程序的生命周期内,只创建一个Bean实例。每次请求该Bean时,都返回同一个实例。这是Spring的默认作用域。
  • Prototype(原型):每次请求该Bean时,都会创建一个新的Bean实例。即每次获取Bean,都返回一个全新的实例。
  • Request(请求):每个HTTP请求都会创建一个新的Bean实例,适用于Web应用程序。
  • Session(会话):每个用户会话(Session)创建一个新的Bean实例,适用于Web应用程序。
  • Application(应用):在整个Web应用程序的生命周期内,只创建一个Bean实例,适用于Web应用程序。
  • WebSocket(Web Socket):在WebSocket会话的生命周期内,每次创建一个新的Bean实例。

scope失效

1、一个作用域为单例的bean,如果要注入其他作用域(非单例)的bean对象,那么这个非单例作用域会失效。

实验:在单例的e中,有成员f,注入,而f是一个多例的作用域。最后的结果是e中获取到的f不是多例,而是同一个。

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

原因在于:
对于单例对象而言,依赖注入仅发生了一次,后续没有再用的多例的F,因此E用的始终是第一次依赖注入的F。

在这里插入图片描述
解决方法1:使用@Lazy注解,添加在要注入的对象上,该注解仅在使用对象时,才会通过f的代理的方法,创建出f,这样调用的f就是多例的。

解决方法2:可以通过在多例对象的scope注解中,指定参数,设置代理模式。

在这里插入图片描述
解决方法3:注入F的工厂,获取方法中,使用工厂构建,然后返回
在这里插入图片描述
解决方法4:注入容器对象,获取方法中,使用容器构建出对象。

9、基于AJC编译器实现AOP

AJC(AspectJ Compiler)是AspectJ编译器的缩写。AspectJ是一种Java语言的扩展,它是AOP(面向切面编程)的一个实现。AspectJ允许开发者在Java代码中直接定义切面(Aspects),从而实现横切关注点的功能,例如日志记录、性能监控、事务管理等。

AJC的实现需要在Maven中引入AJC编译器插件

AJC编译器会直接将@Aspect增加的内容,写入到目标类中。

待增强的类:
在这里插入图片描述
aspect:
在这里插入图片描述
在编译后,生成的target中,可以看到我们的目录类已经被改写,增强的切面内容已经写入了目标类中:
在这里插入图片描述

基于AJC编译器实现的AOP,不同于spring容器中,基于代理的实现。因此AJC增强,不需要借助spring容器,而且它可以增强静态方法,而基于代理实现的增强,它的本质是通过重写方法,而静态方法是不可被重写的。

10、基于agent类加载实现AOP

基于agent类加载实现AOP指的是在在运行时,通过指定系统运行参数,基于agent类加载来实现增强。

实验:
切面指向待增强类中所有的方法:
在这里插入图片描述
运行时虚拟机参数设置:

bashjavaagent:C:\Users\123\.m2\repository/org/aspectj/aspectjweaver/1.9.4/aspectjweaver-1.9.4.jar

AJC在编译阶段实现了AOP增强,因此可以在target中找到编译对象,通过反编译查看增强后的目标类。

基于agent类加载实现的增强,增强的目标运行在JVM中。
可以通过阿里的Arthas工具,调试正在运行的程序:
在这里插入图片描述

通过 jad命令,指定待增强的目标类:
在这里插入图片描述
然后就可以看到类加载增强的内容。
在这里插入图片描述

11、基于JDK动态代理 / CGLIB动态代理 实现AOP

JDK动态代理:对于实现了接口的目标对象,Spring使用JDK动态代理来创建代理对象。JDK动态代理是通过Java原生的java.lang.reflect.Proxy类来实现的。代理对象实现了目标接口,并在InvocationHandler的invoke方法中添加了增强逻辑,即基于反射,method.invoke('待增强对象', '方法参数');

JDK动态代理只能针对接口代理!

在这里插入图片描述

注意:代理对象没有源码,是在运行期间动态生成的字节码,因此代理对象需要传递加载器,将字节码加载对代理对象。
在这里插入图片描述

CGLIB动态代理:对于没有实现接口的目标对象,Spring使用CGLIB动态代理来创建代理对象。CGLIB(Code Generation Library)是一个代码生成库,它通过生成目标类的子类来实现代理。代理对象继承了目标类,并在其子类中添加了增强逻辑。

核心逻辑是基于Code Generation Library中的
Enhancer.create()方法,生成代理类为待增强目标的类的子类。

所以cglib动态代理只能针对可继承的待增强对象进行代理!
在这里插入图片描述

cglib动态代理对于方法的调用有三种:
1、通过方法反射的方式,method.invoke(target,args)
2、通过方法代理对象,传入目标对象调用,非反射,需要目标
3、通过方法代理对象,传入代理对象调用,非反射,需要代理。这里传入的代理是FastClassProxy

12、JDK动态代理实现原理

JDK动态代理是基于反射实现的。

  • 1、代理对象必须实现InvocationHandler接口,JDK在实现时是继承了Proxy类,提供了InvocationHandler的构建方法,在执行时通过super,传入InvocationHandler。
  • 2、使用Proxy.newProxyInstance产生代理对象,代理对象是基于ASM(字节码操作框架)技术,动态生成的字节码,因此需要传入类加载器,将字节码加载为对象。
  • 3、接口方法的获取是通过反射的方式,即从类的字节码中调用getMethod方法得到的,为了避免多次调用的getMethod的开销,代理对象内部使用静态成员保存了方法,并通过静态代码块进行了初始化赋值。
  • 4、为了处理有返回值的方法,代理对象中的返回值为Object对象。方法中对于异常的捕获和处理,分为了运行时异常和受检时异常,对于运行时异常直接抛出,对于受检异常,将其包装为UndeclaredThrowableException后,再抛出。
  • 5、jdk反射优化,接口方法增强时,采用了反射的方式调用方法,这样性能是有损耗的,jdk内部对此进行了优化,当调用次数到第17次时,jdk内部会生成一个有该方法的代理对象,直接调用该代理对象的方法,而不再使用反射的形式调用。

13、CGLib动态代理实现原理

JDK动态代理增强的是实现了接口的目标类,本质上基于反射。
CGLib动态代理采用继承 + 方法拦截器的方式,针对可继承的目标类进行增强。

1、生成代理类:当目标类需要被代理时,CGLIB会在运行时生成一个代理类,该代理类继承自目标类,成为目标类的子类。

2、拦截器:在CGLIB中,代理的逻辑由一个拦截器(MethodInterceptor)来实现,拦截器负责在代理类的方法调用前后执行额外的逻辑。拦截器类似于JDK动态代理中的InvocationHandler。

3、方法调用的重定向:在代理类的方法调用时,CGLIB会将方法的调用重定向到拦截器的intercept()方法中。在intercept()方法中,可以实现对目标方法的增强逻辑,并调用目标方法。

4、代理对象创建:通过字节码生成技术,CGLIB将代理类的定义转换为字节码,并使用ClassLoader加载字节码,最终生成代理对象。

14、MethodProxy

cglib中基于MethodProxy的目标方法调用,是直接调用而非反射,这使得它的性能会优于JDK动态代理的方式。

在CGLIB源码中,MethodProxy类的主要实现是由FastClass类和MethodInfo类配合完成的。下面简要解释MethodProxy的实现原理:

1、FastClass:FastClass是CGLIB中的一个关键类,它负责快速调用一个类的方法,而无需像反射那样通过Method对象进行调用。FastClass通过方法的索引号直接进行方法调用,从而提高了调用的效率。FastClass通过ASM库在运行时生成一个快速调用方法的类。

2、MethodInfo:MethodInfo用于表示目标类中的一个方法。它包含了方法的名称、访问修饰符、返回类型、参数类型等信息。

3、MethodProxy:在生成代理类的过程中,CGLIB会为每个目标方法生成一个对应的MethodProxy对象。MethodProxy中包含了目标方法的索引号和方法签名等信息。

4、在代理类的方法调用时,代理对象会通过MethodProxy的invoke(Object obj, Object[] args)方法来调用目标方法。invoke()方法内部会通过FastClass来快速调用目标方法,而无需使用Java反射。通过FastClass的invoke(int methodIndex, Object obj, Object[] args)方法,根据目标方法的索引号直接调用目标方法。

通过这种方式,CGLIB避免了Java反射带来的性能开销,实现了高性能的动态代理。MethodProxy是实现这一机制的重要组成部分,它使得CGLIB动态代理在对没有实现接口的类进行代理时,具有了更高的效率和性能。

CGLIB和JDK动态代理的实现区别

CGLIB和JDK动态代理是两种不同的动态代理实现方式,它们在原理、适用场景和性能方面有一些区别。下面讲解一下它们的区别:

  • 原理和实现方式:

    • JDK动态代理:JDK动态代理是通过Java原生的java.lang.reflect.Proxy类和InvocationHandler接口来实现的。在运行时,JDK动态代理通过生成目标接口的代理对象,并通过InvocationHandler的invoke()方法来实现对目标方法的拦截和增强。
    • CGLIB动态代理:CGLIB动态代理是通过CGLIB库,利用字节码生成技术,在运行时生成目标类的子类作为代理类。在子类中,CGLIB通过生成MethodProxy对象实现对目标方法的拦截和增强。
  • 代理类型:

    • JDK动态代理:JDK动态代理只能代理实现了接口的目标类。如果目标类没有实现任何接口,就无法使用JDK动态代理进行代理。
    • CGLIB动态代理:CGLIB动态代理可以代理没有实现接口的目标类。它通过生成目标类的子类来实现代理,因此对于没有接口的类也能够代理。
  • 性能:

    • JDK动态代理:JDK动态代理在调用代理方法时,涉及到反射调用,有一定的性能开销。代理效率相对较低,尤其在代理方法较多时性能下降较明显。
    • CGLIB动态代理:CGLIB动态代理在调用代理方法时,通过直接调用生成的子类的方法,无需反射调用,因此相对于JDK动态代理,性能更高。特别适用于代理方法较多或代理对象创建较频繁的情况。
  • 依赖和兼容性:

    • JDK动态代理:JDK动态代理依赖于Java原生的java.lang.reflect.Proxy类,对于Java平台的兼容性较好,无需额外引入第三方库。
    • CGLIB动态代理:CGLIB动态代理依赖于CGLIB库,使用时需要引入相应的依赖。CGLIB动态代理在Java平台上运行良好,但在其他Java虚拟机(JVM)上可能存在兼容性问题。

15、Spring AOP与选择代理

AOP(Aspect Oriented Programming,面向切面编程),其实就是面向特定方法编程,可以是对原来方法的增强,也可以是对原有方法的改编。

例如需要统计某个方法的执行时长分析:
在这里插入图片描述

AOP核心概念

  • 连接点:JoinPoint,可以被AOP控制的方法(暗含方法执行时的相关信息)
  • 通知:Advice,指哪些重复的逻辑,也就是共性功能(最终体现为一个方法)
  • 切入点表达式:PointCut,匹配连接点的条件,通知仅会在切入点方法执行时被应用。通常使用切入点表达式,来匹配切入的方法。
  • 切面:Aspect,描述通知与切入点的对应关系(通知 + 切入点)
  • 单通知切面:Advisor,一种粒度更细的切面,只包含一个通知和切点的切面。
  • 目标对象:Target,通知所应用的对象。

在这里插入图片描述

通知(Advice)类型

  • 前置通知(Before Advice):在目标方法执行之前执行的通知。用于在目标方法执行前做一些预处理操作。

  • 后置通知(After Advice):在目标方法执行之后执行的通知。无论目标方法是否成功执行,后置通知都会执行。

  • 返回通知(After Returning Advice):在目标方法成功执行并返回结果后执行的通知。可以访问目标方法的返回值。

  • 异常通知(After Throwing Advice):在目标方法抛出异常后执行的通知。用于处理异常情况。

  • 环绕通知(Around Advice):在目标方法执行前后都可以执行的通知。它可以完全控制目标方法的执行,包括是否执行目标方法和在何处执行目标方法等。

注: @Around 环绕通知与其他类型通知有所不同:

  • @Around 环绕通知需要自己调用 ProceedingJoinPoint.proceed()来让原始方法执行,如果原始方法有返回值,需赋值给Object对象,而其他通知类型则不需要处理原始方法。
  • @Around 环绕通知的连接点类型为ProceedingJoinPoint,而其他通知的连接点类型为JoinPoint,是ProceedingJoinPoint的父类。

@Order控制通知顺序

当有多个切面的切入点都匹配到了目标方法,多个通知都会执行。那么执行顺序是怎样的呢?

  • 1、不同切面类中,默认按照切面类类名字母排序
    • 目标方法前的通知:字母排序靠前先执行
    • 目标方法后的通知:字母排序靠后先执行
  • 2、可以通@order(数字)注解加在切面类上,执行优先级
    • 目标方法前的通知:数字小的先执行
    • 目标方法后的通知:数字大的先执行

顺序控制只能以切面类为单位,类中的具体的通知方法,无法控制顺序。

在这里插入图片描述

切入点表达式(Pointcut)与@PointCut

使用切入点表达式,来匹配到切入的方法,匹配的方式有:

  • execution(……):根据方法的返回值、包名、类名、方法名、方法参数等信息匹配,使用execution
  • @annotation(……):根据注解匹配
    在这里插入图片描述

切入点表达式可以通过注解@Pointcut抽取出来。然后在需要的地方复用:
在这里插入图片描述

连接点(JoinPoint)

连接点是增强方法的入参,用于获取实际运行方法的信息。
在这里插入图片描述
在这里插入图片描述

基于代码实现的AOP

需要四个步骤:

  • 1、备好切点
  • 2、备好通知
  • 3、备好切面(切点 + 通知)
  • 4、创建代理

在这里插入图片描述
在这里插入图片描述

Spring对于代理的选择规则

Spring 框架会自动根据目标 bean 的特性选择合适的代理方式。这个选择是透明的,开发者无需显式指定使用哪种代理方式。当配置了 Spring AOP 时,如果目标 bean 实现了接口,Spring 将使用 JDK 动态代理;如果目标 bean 没有实现接口,Spring 将使用 CGLIB 代理。

对于上边实验中,使用ProxyFactory创建的代理对象:

  • 如果设置了proxyTargetClass = false,且目标实现了接口,那么用jdk实现。
  • 如果设置了proxyTargetClass = false,目标没有实现接口,则使用cglib实现。
  • 如果设置了proxyTargetClass = true,总是使用cglib实现。

16、切入点匹配

使用切入点表达式,来匹配到切入的方法,匹配的方式有:

  • execution(……):根据方法的返回值、包名、类名、方法名、方法参数等信息匹配,使用execution
  • @annotation(……):根据注解匹配

在这里插入图片描述

17、从@Aspect到@Advisor

Aspect是一种高级切面,实现起来较为简单,可以通过注释:
在这里插入图片描述

Advisor则是一种低级的切面,常在框架实现内部中使用。创建Adivisor需要切点 + 通知(由MethodInterceptor创建)

在这里插入图片描述

Spring启动过程中,会解析所有的切面,如果是高级切面Aspect会转为低级切面Adviser。
在这里插入图片描述

18、通知的执行

基于适配器模式将所有通知转为环绕通知

无论ProxyFactory基于哪种方式(JDK或者CGLib)创建代理,最后调用Advice通知的都是一个MethodInvocation对象,非环绕通知会统一转为环绕通知再执行。

在这里插入图片描述
在这里插入图片描述

基于责任链模式实现通知的执行

在这里插入图片描述

19、动态通知调用

  • 静态通知调用:不带参数绑定
  • 动态通知调用:需要参数绑定

在这里插入图片描述

47、@Autowired底层

@Autowired是按类型来注入的,底层实现比较复杂。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Element-plus侧边栏踩坑

问题描述 el-menu直接嵌套el-menu-item菜单&#xff0c;折叠时不会出现文字显示和小箭头无法隐藏的问题&#xff0c;但是实际开发需求中难免需要把el-menu-item封装为组件 解决 vue3项目中嵌套两层template <template><template v-for"item in list" :k…

1.2 网络安全法律法规

数据参考&#xff1a;CISP官方 目录 国家立法体系网络安全法解析网络安全相关法律 一、国家立法体系 1、我国的立法体系 我国的立法体系在网络空间治理中扮演着基础工作的角色。为了应对快速发展的网络技术和威胁&#xff0c;我国采取了多级立法机制来完善网络空间的法律…

腾讯云 Cloud Studio 实战训练营——快速构建React完成点餐H5页面

目录 一、前言 1、什么是腾讯云 Cloud Studio 2、本文实验介绍 二、前期准备工作 1、注册 Cloud Studio 2、初始化工作空间 三、开发一个简版的点餐系统页面 1、安装依赖 1.1、安装 antd-mobile 1.2、安装 less 和 less-loader 1.3、暴露 webpack 配置文件 1.4、安…

FPGA设计时序分析三、恢复/去除时间

目录 一、背景说明 二、工程设计 2.1 工程代码 2.2 综合结果 一、背景说明 ​恢复时间recovery和去除时间removal和setup、holdup类型&#xff0c;不同点是数据信号为控制信号&#xff0c;如复位&#xff0c;清零&#xff0c;使能信号&#xff0c;更多的是异步的复位信号&a…

代理模式——对象的间接访问

1、简介 1.1、概述 由于某些原因&#xff0c;客户端不想或不能直接访问某个对象&#xff0c;此时可以通过一个被称为“代理”的第三者来实现间接访问&#xff0c;该方案对应的设计模式被称为代理模式。 代理模式是一种应用很广泛的结构型设计模式&#xff0c;而且变化很多。…

使用MyBatis(2)

目录 一、定义接口、实体类、创建XML文件实现接口&#xff09; 二、MyBatis的增删改查 &#x1f345;1、MyBatis传递参数查询 &#x1f388;写法一 &#x1f388;写法二 &#x1f388;两种方式的区别 &#x1f345;2、删除操作 &#x1f345;3、根据id修改用户名 &#x…

WPF线程使用详解:提升应用性能和响应能力

在WPF应用程序开发中&#xff0c;线程的合理使用是保证应用性能和响应能力的关键。WPF提供了多种线程处理方式&#xff0c;包括UI线程、后台线程、Task/Async Await和BackgroundWorker。这些方式与传统的Thread类相比&#xff0c;更加适用于WPF框架&#xff0c;并能够简化线程操…

使用pikachu管理工具下的XSS后台进行实战

写在前面的重要提示&#xff1a; Attention&#xff1a;技术没有好坏之分&#xff0c;关键在于使用技术的人或组织。网络安全技术是一把双刃剑 – 作为网络安全人&#xff0c;虽然无法控制头上的帽子是否会变绿&#xff0c;但能控制不让它变黑&#xff1b;无论我们在物质上面对…

深度学习实践——卷积神经网络实践:裂缝识别

深度学习实践——卷积神经网络实践&#xff1a;裂缝识别 系列实验 深度学习实践——卷积神经网络实践&#xff1a;裂缝识别 深度学习实践——循环神经网络实践 深度学习实践——模型部署优化实践 深度学习实践——模型推理优化练习 深度学习实践——卷积神经网络实践&#xff…

VUE之VueRouter页面跳转

参考资料&#xff1a; 参考视频 参考demo及视频资料 VUE之基本部署及VScode常用插件 VUE之基本组成和使用 VUE之Bootstrap和Element-UI的使用 VUE之axios使用&#xff0c;跨域问题&#xff0c;拦截器添加Token Vue Router官网 Vue Router说明&#xff1a; 说明&#xf…

【计算机网络】10、ethtool

文章目录 一、ethtool1.1 常见操作1.1.1 展示设备属性1.1.2 改变网卡属性1.1.2.1 Auto-negotiation1.1.2.2 Speed 1.1.3 展示网卡驱动设置1.1.4 只展示 Auto-negotiation, RX and TX1.1.5 展示统计1.1.7 排除网络故障1.1.8 通过网口的 LED 区分网卡1.1.9 持久化配置&#xff08…

详细介绍 React 中如何使用 redux

在使用之前要先了解它的配套插件&#xff1a; 在React中使用redux&#xff0c;官方要求安装其他插件 Redux Toolkit 和 react-redux Redux Toolkit&#xff1a;它是一个官方推荐的工具集&#xff0c;旨在简化 Redux 的使用和管理。Redux Toolkit 提供了一些提高开发效率的工具…

GO语言日志切割 + 记录调用源

准备工作 日志记录对程序排查问题比较关键&#xff0c;记录下GO中日志选择&#xff0c;从以下出发点考虑&#xff1a; 日志文件能自动切割&#xff0c;以免过大能记录从哪个文件哪行代码调用的&#xff0c;方便排查问题配置简单明了库文件使用人数较多&#xff0c;稳定 经过一段…

ChatIE:通过多轮问答问题实现实命名实体识别和关系事件的零样本信息抽取,并在NYT11-HRL等数据集上超过了全监督模型

项目设计集合&#xff08;人工智能方向&#xff09;&#xff1a;助力新人快速实战掌握技能、自主完成项目设计升级&#xff0c;提升自身的硬实力&#xff08;不仅限NLP、知识图谱、计算机视觉等领域&#xff09;&#xff1a;汇总有意义的项目设计集合&#xff0c;助力新人快速实…

python读取json文件

import json# 文件路径(同目录文件名即可,不同目录需要绝对路径) path 1.json# 读取JSON文件 with open(path, r, encodingutf-8) as file:data json.load(file)#data为字典 print(data) print(type(data))

文件上传

js绕过 打开网页尝试上传一句话木马&#xff0c;发现只能上传图片文件 审计源代码&#xff0c;发现使用一个checkfile函数js对文件类型进行了屏蔽 于是我们修改网页代码&#xff0c;去除返回值的检查函数 checkFile() 上传成功&#xff0c;使用蚁剑连接 连接成功 .htaccess绕…

element-ui使用动态渲染下拉选择框el-select已经选择的下拉框的值不可以重复选择让其disabled

调接口拿到下拉框数据的数据的时候将其disabled全为true 但是如果编辑的时候就需要与详情接口对比&#xff0c;如果有id一致就将disabled为true if (res.code 0) {if (this.dialogtitle "新增合同") {res.data.map((v) > {v.nameUnitVoList.forEach((item) >…

小程序新渲染引擎 Skyline 发布正式版

为了进一步提升小程序的渲染性能和体验&#xff0c;我们推出了一套新渲染引擎 Skyline&#xff0c;现在&#xff0c;跟随着基础库 3.0.0 发布 Skyline 正式版。 我们知道&#xff0c;小程序一直用 WebView 来渲染界面&#xff0c;因其有不错的兼容性和丰富的特性&#xff0c;且…

lc209.长度最小的子数组

暴力破解&#xff1a;二次for循环遍历num[i]...num[j]&#xff0c;记录满足条件的最小长度 前缀和二分&#xff1a;前缀和降低计算num[i]...num[j]的时间复杂度 对前缀和数组中的每个数进行遍历&#xff0c;找到距离这个数满足条件的最小长度 前缀和数组单调递增&#xff0c;此…

最小时间差(力扣)排序 + 思维 JAVA

给定一个 24 小时制&#xff08;小时:分钟 “HH:MM”&#xff09;的时间列表&#xff0c;找出列表中任意两个时间的最小时间差并以分钟数表示。 示例 1&#xff1a; 输入&#xff1a;timePoints [“23:59”,“00:00”] 输出&#xff1a;1 示例 2&#xff1a; 输入&#xff1a;…
最新文章