09.AOP-尚硅谷Spring零基础入门到进阶,一套搞定spring6全套视频教程(源码级讲解)

news2025/2/25 1:24:14

现有代码缺陷
针对带日志功能的实现类,我们发现有如下缺陷:

  • 对核心业务功能有干扰,导致程序员在开发核心业务功能时分散了精力
  • 附加功能分散在各个业务功能方法中,不利于统一维护
    解决思路
    解决核心:解耦。把附加功能从业务功能代码中抽取出来。
    困难
    解决问题的困难:要抽取的代码在方法内部,靠以前把子类中的重复代码抽取到父类的方式没法解决。所以需要引
    入新的技术。

代理模式

概念

介绍
二十三种设计模式中的一种,属于结构型模式。它的作用就是通过提供一个代理类,让我们在调用目标方法的时
候,不再是直接对目标方法进行调用,而是通过代理类间接调用。让不属于目标方法核心逻辑的代码从目标方法中
剥离出来一一解耦。调用目标方法时先调用代理对象的方法,减少对目标方法的调用和打扰,同时让附加功能能够
集中在一起也有利于统一维护。
相关术语
,代理:将非核心逻辑剥离出来以后,封装这些非核心逻辑的类、对象、方法。
·目标:被代理“套用”了非核心逻辑代码的类、对象、方法。

场景模拟

  1. 声明计算器接口Calculator,包含加减乘除的抽象方法

    package org.example;  
    
    public interface Calculator {  
        public int add(int i, int j);  
    
        public int sub(int i, int j);  
    
        public int mul(int i, int j);  
    
        public int div(int i, int j);  
    }
    
  2. 写一个实现Calculator业务的实现类

    package org.example;
    public class CalculatorImpl implements Calculator {
        @Override
        public int add(int i, int j) {
            int result = i + j;
            System.out.println("result=" + result);
            return result;
        }
        @Override
        public int sub(int i, int j) {
            int result = i - j;
            System.out.println("result=" + result);
            return result;
        }
        @Override
        public int mul(int i, int j) {
            int result = i * j;
            System.out.println("result=" + result);
            return result;
        }
        @Override
        public int div(int i, int j) {
            int result = i / j;
            System.out.println("result=" + result);
            return result;
        }
    }
    
  3. 写一个实现Calculator业务的带有日志功能的实现类

    package org.example;  
    public class CalculatorLogImpl implements Calculator {
        @Override
        public int add(int i, int j) {
            System.out.println("计算开始,i=" + i + "j=" + j);
            int result = i + j;
            System.out.println("计算结束,i=" + i + "j=" + j + "result=" + result);
            System.out.println("result=" + result);
            return result;
        }
        @Override
        public int sub(int i, int j) {
            System.out.println("计算开始,i=" + i + "j=" + j);
            int result = i - j;
            System.out.println("计算结束,i=" + i + "j=" + j + "result=" + result);
            System.out.println("result=" + result);
            return result;
        }
        @Override
        public int mul(int i, int j) {
            System.out.println("计算开始,i=" + i + "j=" + j);
            int result = i * j;
            System.out.println("计算结束,i=" + i + "j=" + j + "result=" + result);
            System.out.println("result=" + result);
            return result;
        }
        @Override
        public int div(int i, int j) {
            System.out.println("计算开始,i=" + i + "j=" + j);
            int result = i / j;
            System.out.println("计算结束,i=" + i + "j=" + j + "result=" + result);
            System.out.println("result=" + result);
            return result;
        }
    }
    

静态代理

静态代理确实实现了解耦,但是由于代码都写死了,完全不具备任何的灵活性。就拿日志功能来说,将来其
他地方也需要附加日志,那还得再声明更多个静态代理类,那就产生了大量重复的代码,日志功能还是分散
的,没有统一管理。
提出进一步的需求:将日志功能集中到一个代理类中,将来有任何日志需求,都通过这一个代理类来实现。
这就需要使用动态代理技术了。

动态代理

使用java.lang.reflect.Proxy类实现动态代理
官方示例代码

InvocationHandler handler = new MyInvocationHandler(...);  
Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),  
        new class<?>[]{Foo.class},  
        handler);

创建一个代理工厂类

package org.example;  
  
import lombok.val;  
  
import javax.print.attribute.standard.JobKOctets;  
import java.lang.reflect.InvocationHandler;  
import java.lang.reflect.Method;  
import java.lang.reflect.Proxy;  
  
public class ProxyFactory {  
    Object target;  
  
    public ProxyFactory(Object target) {  
        this.target = target;  
    }  
  
    public Object getProxy() {  
/*      有三个参数  
        第一个参数:CLassLoader:加载动态生成代理类的来加载器  
        第二个参数:CLass[]interfaces:目录对象实现的所有接口cLass类型数组  
        第三个参数:InvocationHandler:设置代理对象实现目标对象方法的过程*/  
        ClassLoader cLassLoader = target.getClass().getClassLoader();  
        Class[] classes = target.getClass().getInterfaces();  
        InvocationHandler invocationHandler = new InvocationHandler() {  
            @Override  
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
                //调用方法前日志  
                System.out.println("[动态代理][调用前日志]" + method.getName() + "参数:" + args);  
                //调用目标方法  
                Object result = method.invoke(target, args);  
                //调用方法后日志  
                System.out.println("[动态代理][调用后日志]" + method.getName() + "参数:" + args);  
                return result;  
            }  
        };  
        return Proxy.newProxyInstance(cLassLoader, classes, invocationHandler);  
    }  
}

编写测试类

@Test  
public void calculatorTest(){  
    ProxyFactory proxyFactory=new ProxyFactory(new CalculatorImpl());  
    Calculator proxy=(Calculator) proxyFactory.getProxy();  
    proxy.add(1,1);  
}

输出结果

[动态代理][调用前日志]add参数:[Ljava.lang.Object;@7d0587f1
result=2
[动态代理][调用后日志]add参数:[Ljava.lang.Object;@7d0587f1

基于注解的AOP

动态代理分类:JDK动态代理和cglib动态代理
JDK动态代理生成接口实现类代理对象
cglib动态代理继承被代理的目标类,生成子类代理对象,不需要目标类实现接口

  • 有接口可以使用JDK动态代理和cblib动态代理
  • 没有接口只能使用cblib动态代理
    Aspect:是AOP思想的一种实现。本质上是静态代理,将代理逻辑“织入"被代理的目标类编译得到的字节码
    文件,所以最终效果是动态的。weaver就是织入器。Spring只是借用了Aspect)中的注解。

使用AOP步骤

  1. 引入aop相关依赖

    <!--spring aop依赖-->  
    <dependency>  
        <groupId>org.springframework</groupId>  
        <artifactId>spring-aop</artifactId>  
        <version>6.0.2</version>  
    </dependency>  
    <!--spring aspects依赖-->  
    <dependency>  
        <groupId>org.springframework</groupId>  
        <artifactId>spring-aspects</artifactId>  
        <version>6.0.2</version>  
    </dependency>
    
  2. 创建目标资源

    1. 接口

      package com.example.annoAOP;  
      
      public interface Calculator {  
          public int add(int i, int j);  
      
          public int sub(int i, int j);  
      
          public int mul(int i, int j);  
      
          public int div(int i, int j);  
      }
      
    2. 实现类

      package com.example.annoAOP;  
      
      import org.springframework.stereotype.Component;  
      
      @Component  
      public class CalculatorImpl implements Calculator {  
          @Override  
          public int add(int i, int j) {  
              int result = i + j;  
              System.out.println("result=" + result);  
              return result;  
          }  
      
          @Override  
          public int sub(int i, int j) {  
              int result = i - j;  
              System.out.println("result=" + result);  
              return result;  
          }  
      
          @Override  
          public int mul(int i, int j) {  
              int result = i * j;  
              System.out.println("result=" + result);  
              return result;  
          }  
      
          @Override  
          public int div(int i, int j) {  
              int result = i / j;  
              System.out.println("result=" + result);  
              return result;  
          }  
      }
      

第三步创建切面类

  1. 创建bean.xml,使用AOP约束,开启AOP功能和扫描功能

    <?xml version="1.0" encoding="UTF-8"?>  
    <beans xmlns="http://www.springframework.org/schema/beans"  
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
           xmlns:context="http://www.springframework.org/schema/context"  
           xmlns:aop="http://www.springframework.org/schema/aop"  
           xsi:schemaLocation="http://www.springframework.org/schema/beans  
        http://www.springframework.org/schema/beans/spring-beans.xsd    http://www.springframework.org/schema/context    http://www.springframework.org/schema/context/spring-context.xsd    http://www.springframework.org/schema/aop  
        http://www.springframework.org/schema/aop/spring-aop.xsd">  
        <!-- 开启组件扫描           -->  
        <context:component-scan base-package="com.example"/>  
        <!--开启aspectj自动代理,为目标对象生成代理-->  
        <aop:aspectj-autoproxy></aop:aspectj-autoproxy>  
    </beans>
    
  2. 创建LogAscept类,增加一个方法的前置切入点

    package com.example.annoAOP;  
      
    import org.aspectj.lang.annotation.Aspect;  
    import org.aspectj.lang.annotation.Before;  
    import org.springframework.stereotype.Component;  
      
    @Aspect//表明这是一个AOP文件  
    @Component//让IoC进行管理  
    public class LogAspect {  
      
        //设置切入点和通知类型  
        //通知类型:  
        // 前置   @Before(value="切入点表达式")  
        // 返回   @AfterReturning    // 异常   @AfterThrowing    // 后置   @After()    // 环绕   @Around()    //切入点表达式写法:execution(权限修饰 方法返回值 方法所在全类名.方法名 (参数列表))  
        //execution:固定语法  
        //权限修饰:这里写*表示权限修饰符和返回值任意  
        //方法所在全类名:写*表示任意包名;写*...表示包名任意同时包层次深度任意  
        //类名用*号代替表示类名任意,部分用*代替,如*Service,表示匹配以Service结尾的列或接口  
        //方法名:用*号代替表示方法名任意;部分用*代替,如get*,表示匹配以get开头的方法  
        //参数列表可以使用(...)形式表示参数列表任意  
      
        @Before(value = "execution(public int com.example.annoAOP.CalculatorImpl.add (int,int))")  
        public void beforeAdd() {  
            System.out.println("[前置通知][add()]计算开始");  
        }  
    }
    

    方法表达式写法:

    在这里插入图片描述

  3. 创建测试方法

    @Test
    public void testAOPAdd(){
       ApplicationContext applicationContext=new ClassPathXmlApplicationContext("bean.xml");
       Calculator calculator=applicationContext.getBean(Calculator.class);
       	calculator.add(1,1);
    }
    
  4. 输出结果

    [前置通知][add()]计算开始
    result=2
    

通知类型

  • 前置通知:在被代理的目标方法前执行
  • 返回通知:在被代理的目标方法成功结束后执行(寿终正寝)
  • 异常通知:在被代理的目标方法异常结束后执行(死于非命)
  • 后置通知:在被代理的目标方法最终结束后执行(盖棺定论)
  • 环绕通知:使用try.catch.finally结构围绕整个被代理的目标方法,包括上面四种通知对应的所有位置
    修改LogAspect类,添加五种通知方法
package com.example.annoAOP;  
  
import org.aspectj.lang.JoinPoint;  
import org.aspectj.lang.ProceedingJoinPoint;  
import org.aspectj.lang.annotation.*;  
import org.springframework.stereotype.Component;  
  
@Aspect//表明这是一个AOP文件  
@Component//让IoC进行管理  
public class LogAspect {  
  
    //前置通知  
    @Before(value = "execution(* com.example.annoAOP.CalculatorImpl.* (..))")  
    public void beforeMethod(JoinPoint joinPoint) {  
        String MethodName = joinPoint.getSignature().getName();  
        Object[] args = joinPoint.getArgs();  
        System.out.println("[前置通知][CalculatorImpl.MethodName=" + MethodName + "()");  
        System.out.println("Args[]=" + args);  
    }  
  
    //后置通知  
    @After(value = "execution(* com.example.annoAOP.CalculatorImpl.* (..))")  
    public void afterMethod(JoinPoint joinPoint) {  
        String MethodName = joinPoint.getSignature().getName();  
        Object[] args = joinPoint.getArgs();  
        System.out.println("[后置通知][CalculatorImpl.MethodName=" + MethodName + "()");  
        System.out.println("Args[]=" + args);  
    }  
  
    //返回通知  
    @AfterReturning(value = "execution(* com.example.annoAOP.CalculatorImpl.* (..))", returning = "result")  
    public void afterReturnMethod(JoinPoint joinPoint, Object result) {  
        String MethodName = joinPoint.getSignature().getName();  
        System.out.println("[返回通知][CalculatorImpl.MethodName=" + MethodName + "()");  
        System.out.println("[返回通知]result=" + result);  
    }  
  
    //异常通知  
    @AfterThrowing(value = "execution(* com.example.annoAOP.CalculatorImpl.* (..))", throwing = "exp")  
    public void afterThrowing(JoinPoint joinPoint, Throwable exp) {  
        String MethodName = joinPoint.getSignature().getName();  
        System.out.println("[异常通知][CalculatorImpl.MethodName=" + MethodName + "()");  
        System.out.println(exp);  
    }  
  
    //环绕通知  
    @Around("execution(* com.example.annoAOP.CalculatorImpl.* (..))")  
    //ProceedingJoinPoint继承JoinPoint,比JoinPoint功能更强大,可以更好的调用目标方法  
    public Object around(ProceedingJoinPoint joinPoint) {  
        Object result = null;  
        try {  
            System.out.println("环绕通知-目标方法执行前");  
            result = joinPoint.proceed();  
            System.out.println("环绕通知-目标方法执行后");  
        } catch (Throwable throwable) {  
            System.out.println("环绕通知-目标方法执行异常");  
        } finally {  
            System.out.println("环绕通知-目标方法执行完成");  
        }  
        return result;  
    }  
}

输出结果

环绕通知-目标方法执行前
[前置通知][CalculatorImpl.MethodName=add()
Args[]=[Ljava.lang.Object;@62727399
result=2
[返回通知][CalculatorImpl.MethodName=add()
[返回通知]result=2
[后置通知][CalculatorImpl.MethodName=add()
Args[]=[Ljava.lang.Object;@62727399
环绕通知-目标方法执行后
环绕通知-目标方法执行完成

编写测试方法,使测试方法引发异常

@Test  
public void testAOPexp(){  
    ApplicationContext applicationContext=new ClassPathXmlApplicationContext("bean.xml");  
    Calculator calculator=applicationContext.getBean(Calculator.class);  
    calculator.div(1,0);  
}

运行结果

环绕通知-目标方法执行前
[前置通知][CalculatorImpl.MethodName=div()
Args[]=[Ljava.lang.Object;@4d9ac0b4
[异常通知][CalculatorImpl.MethodName=div()
java.lang.ArithmeticException: / by zero
[后置通知][CalculatorImpl.MethodName=div()
Args[]=[Ljava.lang.Object;@4d9ac0b4
环绕通知-目标方法执行异常
环绕通知-目标方法执行完成

[之后是异常报错信息]

重用切入点

  1. 定义一个切入点

    	package com.example.annoAOP;
    @Pointcut(value = "execution(* com.example.annoAOP.CalculatorImpl.* (..))")  
    public void pointCut() {}
    
  2. 使用切入点

    1. 内部使用切入点

      @After(value = "pointCut")  
      public void afterMethod(JoinPoint joinPoint) {  
          String MethodName = joinPoint.getSignature().getName();  
          Object[] args = joinPoint.getArgs();  
          System.out.println("[后置通知][CalculatorImpl.MethodName=" + MethodName + "()");  
          System.out.println("Args[]=" + args);  
      }  
      
    2. 外部使用切入点

      @After(value = "com.example.annoAOP.pointCut")  
      public void afterMethod(JoinPoint joinPoint) {  
          String MethodName = joinPoint.getSignature().getName();  
          Object[] args = joinPoint.getArgs();  
          System.out.println("[后置通知][CalculatorImpl.MethodName=" + MethodName + "()");  
          System.out.println("Args[]=" + args);  
      }  
      

切面的优先级

相同目标方法上同时存在多个切面时,切面的优先级控制切面的内外嵌套顺序。

  • 优先级高的切面:外面
  • 优先级低的切面:里面
    使用@Order注解可以控制切面的优先级:
  • @Order(较小的数):优先级高
  • @Order(较大的数):优先级低

XML形式配置AOP

  1. 创建新包xmlaop,复制上文接口、实现类、AOP配置类

  2. 删除LogAspect类的@Aspect注解和AOP注解

  3. 新建XmlAop.xml配置文件

    <?xml version="1.0" encoding="UTF-8"?>  
    <beans xmlns="http://www.springframework.org/schema/beans"  
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
           xmlns:context="http://www.springframework.org/schema/context"  
           xmlns:aop="http://www.springframework.org/schema/aop"  
           xsi:schemaLocation="http://www.springframework.org/schema/beans  
        http://www.springframework.org/schema/beans/spring-beans.xsd    http://www.springframework.org/schema/context    http://www.springframework.org/schema/context/spring-context.xsd    http://www.springframework.org/schema/aop    http://www.springframework.org/schema/aop/spring-aop.xsd">  
        <!-- 开启组件扫描           -->  
        <context:component-scan base-package="com.example.xmlAOP"/>  
        <!--配置AOP-->  
        <aop:config>  
            <!-- 配置切面类       -->  
            <aop:aspect ref="logAspect">  
                <!-- 配置切入点       -->  
                <aop:pointcut id="cutpoint" expression="execution(* com.example.xmlAOP.CalculatorImpl.* (..))"/>  
                <!-- 配置方法执行前通知       -->  
                <aop:before method="beforeMethod" pointcut-ref="cutpoint"/>  
                <!-- 配置方法执行后通知       -->  
                <aop:after method="afterMethod" pointcut-ref="cutpoint"/>  
                <!-- 配置方法返回后通知       -->  
                <aop:after-returning method="afterReturnMethod" pointcut-ref="cutpoint" returning="result"/>  
                <!-- 配置环绕通知       -->  
                <aop:around method="around" pointcut-ref="cutpoint"/>  
                <!-- 配置异常通知       -->  
                <aop:after-throwing method="afterThrowing" pointcut-ref="cutpoint" throwing="exp"/>  
            </aop:aspect>  
    
        </aop:config>  
    
    </beans>
    
  4. 编写测试方法

    @Test  
    public void testXML_AOP(){
        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("XmlAop.xml");
        //本项目存在两个Calculator,需要注意使用的是哪个Calculator类
        com.example.xmlAOP.Calculator calculator=applicationContext.getBean(com.example.xmlAOP.Calculator.class);
        calculator.add(1,1);
    }
    
  5. 输出结果

[前置通知][CalculatorImpl.MethodName=add()
Args[]=[Ljava.lang.Object;@eda25e5
环绕通知-目标方法执行前
result=2
环绕通知-目标方法执行后
环绕通知-目标方法执行完成
[返回通知][CalculatorImpl.MethodName=add()
[返回通知]result=2
[后置通知][CalculatorImpl.MethodName=add()
Args[]=[Ljava.lang.Object;@eda25e5

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

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

相关文章

华为官方出品:《应用现代化实践指南》电子书,可免费下载

本期云享书库为各位开发者带来了应用现代化方面的技术内容。 在数字化时代&#xff0c;企业面临着前所未有的机遇与挑战。随着技术的飞速发展&#xff0c;特别是云计算、大数据、人工智能&#xff08;AI&#xff09;和机器学习&#xff08;ML&#xff09;的兴起&#xff0c;正…

中国科学院地理所牛书丽团队《Global Change Biology 》最新成果!

本文首发于“生态学者”微信公众号&#xff01; 在全球气候变化的背景下&#xff0c;干旱地区的扩张对生态系统的氮循环产生了深远影响。氮同位素&#xff08;δ15N&#xff09;的天然丰度&#xff0c;尤其是土壤中的δ15N&#xff0c;是评估陆地生态系统氮循环动态和氮限制的关…

你的数据库真的规范吗?小心这些“潜在风险”!

这个简单的小功能&#xff0c;解决了无数企业最头疼的问题。 分享个比较常见的案例。某个客户&#xff0c;在全国范围有近千万的注册用户&#xff0c;日均交易量数十万笔。企业使用 MySQL 数据库存储核心业务数据&#xff0c;包括用户信息、订单信息、商品信息等。某天&#x…

windows信息收集和提权

目录 手动收集 工具收集 windows本地内核提权 本地提权 根据windows去找需要的exp进行利用 提权后结合mimikatz使用 msf提权 简单提权 生成后门 上线 BypassUAC绕过UAC提权 msf带的bypassuac模块可以尝试提权 Bypassuac提权命令操作 提权成功 ​local_exploi…

c++多态的定义和原理

目录 1、多态的定义和实现 1.多态的构成条件 2.虚函数 3.虚函数的重写(覆盖) 4.虚函数重写的两个例外 5.c11 override和final 6.重载&#xff0c;覆盖(重写)和隐藏(重定义) 2、抽象类 概念 接口继承和实现继承 3、多态的原理 1.虚函数表 2.多态的原理 4、多继承中的虚…

deep learning 环境配置

1 NVIDIA驱动安装 ref link: https://blog.csdn.net/weixin_37926734/article/details/123033286 2 cuda安装 ref link: https://blog.csdn.net/qq_63379469/article/details/123319269 进去网站 https://developer.nvidia.com/cuda-toolkit-archive 选择想要安装的cuda版…

城市智慧公厕-为用户提供最直观的上厕所指引

在智慧城市的发展进程中&#xff0c;城市智慧公厕作为公共服务设施的智能化升级版&#xff0c;正悄然改变着我们日常生活中的一个基本需求——如厕体验。它不仅提升了公共卫生水平&#xff0c;还为城市居民和游客提供了前所未有的便利&#xff0c;成为展现城市文明程度和科技实…

DDR3 (四)

1 DDR3 8倍预取 DDR3相比DDR2外部IO时钟又提高了一倍&#xff0c;因此DDR3外部IO时钟是内核时钟的4倍&#xff0c;再加上双沿采样&#xff0c;因此DDR3可以实现8倍预取 2 DDR3 芯片位宽 DDR3使用8倍预取技术&#xff0c;指的是芯片位宽&#xff08;DQ数据线位宽&#xff09…

ST7789 linux4.x驱动

文章目录 ST7789 linux4.x驱动设备树配置驱动程序编译驱动测试驱动 ST7789 linux4.x驱动 设备树配置 pinctrl_ecspi2_cs_1: ecspi2_cs_grp-1 {fsl,pins <MX6UL_PAD_CSI_DATA01__GPIO4_IO22 0x40017059>; };pinctrl_ecspi2_1: escpi2grp {fsl,pins <MX6UL_PAD_CSI_…

【开发工具】webStrom2024版-永久使用

1、解压文件 2、安装步骤 先执行unistall-current-user.vbs&#xff0c;确保当前环境变量下没有历史使用记录。再执行install-current-user.vbs。运行的时候&#xff0c;会有第一个弹窗&#xff0c;点击确定&#xff0c;稍微等待一会&#xff0c;会出现 Done 的弹窗&#xff0…

前端最全面试题【最新版本2024-7月】

文章目录 最常见问题javascript篇Javascript的运行机制javascript的数据类型怎样判断变量的类型数据类型转换闭包的优缺点v-if和v-for哪个优先级更高&#xff1f; 如果两个同时出现&#xff0c;应该怎么优化得到更好的性能&#xff1f;HTML5的新特性和CSS3的新特性div 上下居中…

流失人数月度统计教程

文章目录 一、ABC轮线1、数据源&#xff1a;每个月最后一天数据2、填写 "B轮&#xff08;直播间&#xff09;-流失人数(个人数据)" 一、ABC轮线 以B轮直播间数据填写为例 1、数据源&#xff1a;每个月最后一天数据 如7月&#xff0c;即为7月31日 2、填写 “B轮&…

x264 编码器 AArch64 汇编函数模块关系分析

x264 编码器 AArch64 汇编介绍 x264 是一个流行的开源视频编码器,它实现了 H.264/MPEG-4 AVC 标准。x264 项目致力于提供一个高性能、高质量的编码器,支持多种平台和架构。对于 AArch64(即 64 位 ARM 架构),x264 编码器利用该架构的特性来优化编码过程。在 x264 编码器中,…

Wireshark 对 https 请求抓包并展示为明文

文章目录 1、目标2、环境准备3、Wireshark 基本使用4、操作步骤4.1、彻底关闭 Chrome 进程4.2、配置 SSLKEYLOGFILE [核心步骤]4.3、把文件路径配置到 Wireshark 指定位置4.4、在浏览器发起请求4.5、抓包配置4.6、过滤4.6.1、过滤域名 http.host contains "baidu.com4.6.2…

【Linux】进程间通信之System V共享内存

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前正在学习c和算法 ✈️专栏&#xff1a;Linux &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章有啥瑕疵&#xff0c;希望大佬指点一二 如果文章对…

凯中精密:下一个正丹吗?

业绩预增超十倍&#xff01; 又一匹A股业绩黑马诞生——凯中精密 近期&#xff0c;凯中精密发布2024年上半年业绩预告&#xff0c;预计净利润增速高达1068%至1402%。 从23年的209.54%到24年Q1惊人的6885.78%&#xff0c;再到24年上半年的十倍增速&#xff0c;这条业绩黑马利润…

HNU-2024操作系统实验-Lab9-Shell

一、 实验目的 理解Shell程序的原理、底层逻辑和Shell依赖的数据结构等 在操作系统内核MiniEuler上实现一个可用的Shell程序 能够根据相关原理编写一条可用的Shell指令 二、 实验过程 首先从底层出发&#xff0c;实现Shell程序 1.在src/include目录下新建prt_shell.h头文…

Splashtop 在医疗与制药领域的业务增长近五倍

2024年7月10日 加利福尼亚州库比蒂诺 Splashtop 是安全远程访问和 IT 支持解决方案领域的领先企业&#xff0c;该公司今天宣布&#xff0c;在医疗与制药领域业务同比增长492%&#xff0c;取得了里程碑式的成就。快速发展的数字实验室环境和持续的网络安全威胁需要实施无缝、安…

AWS无服务器 应用程序开发—第十七章 Application Composer

Application Composer 是 AWS 提供的一种可视化工具&#xff0c;用于设计和构建无服务器应用程序。它通过拖放界面简化了无服务器架构的创建过程&#xff0c;使开发者能够更直观地设计和配置应用程序的各个组件。 主要功能 可视化设计 通过拖放界面&#xff0c;开发者可以轻…

科技与水利的完美融合:从数据采集到智能决策,全面解析智慧水利解决方案如何助力水利行业实现智能化管理

本文关键词&#xff1a;智慧水利、智慧水利工程、智慧水利发展前景、智慧水利技术、智慧水利信息化系统、智慧水利解决方案、数字水利和智慧水利、数字水利工程、数字水利建设、数字水利概念、人水和协、智慧水库、智慧水库管理平台、智慧水库建设方案、智慧水库解决方案、智慧…