当前位置: 首页 > news >正文

mini-spring源码分析

IOC模块

关键解释

beanFactory:beanFactory是一个hashMap, key为beanName, Value为 beanDefination

beanDefination:

BeanDefinitionRegistry,BeanDefinition注册表接口,定义注册BeanDefinition的方法

beanReference:增加BeanReference类,包装一个bean对另一个bean的引用。实例化beanA后填充属性时,若PropertyValue#value为BeanReference,引用beanB,则先去实例化beanB。 由于不想增加代码的复杂度提高理解难度,暂时不支持循环依赖,后面会在高级篇中解决该问题

Resource:

BeanFactoryPostProcessor和BeanPostProcessor是spring框架中具有重量级地位的两个接口,理解了这两个接口的作用,基本就理解spring的核心原理了。为了降低理解难度分两个小节实现。

BeanFactoryPostProcessor是spring提供的容器扩展机制,允许我们在bean实例化之前修改bean的定义信息即BeanDefinition的信息。其重要的实现类有PropertyPlaceholderConfigurer和CustomEditorConfigurer,PropertyPlaceholderConfigurer的作用是用properties文件的配置值替换xml文件中的占位符,CustomEditorConfigurer的作用是实现类型转换。BeanFactoryPostProcessor的实现比较简单,看单元测试BeanFactoryPostProcessorAndBeanPostProcessorTest#testBeanFactoryPostProcessor追下代码。

BeanPostProcessor也是spring提供的容器扩展机制,不同于BeanFactoryPostProcessor的是,BeanPostProcessor在bean实例化后修改bean或替换bean。BeanPostProcessor是后面实现AOP的关键

//在bean实例化之前,执行BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(beanFactory);

然后重写beanFactory方法,对入参beanFactory进行interface 重写。

应用上下文ApplicationContext是spring中较之于BeanFactory更为先进的IOC容器,ApplicationContext除了拥有BeanFactory的所有功能外,还支持特殊类型bean如上一节中的BeanFactoryPostProcessor和BeanPostProcessor的自动识别、资源加载、容器事件和监听器、国际化支持、单例bean自动初始化等。

BeanFactory是spring的基础设施,面向spring本身;而ApplicationContext面向spring的使用者,应用场合使用ApplicationContext。

具体实现查看AbstractApplicationContext#refresh方法即可。注意BeanFactoryPostProcessor和BeanPostProcessor的自动识别,这样就可以在xml文件中配置二者而不需要像上一节一样手动添加到容器中了。

ApplicationContext把使用者的步骤打包了

getBeanOfType 

@Override
public <T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException {Map<String, T> result = new HashMap<>();beanDefinitionMap.forEach((beanName, beanDefinition) -> {Class beanClass = beanDefinition.getBeanClass();if (type.isAssignableFrom(beanClass)) {T bean = (T) getBean(beanName);result.put(beanName, bean);}});return result;
}

ApplicationContext容器提供了完善的事件发布和事件监听功能。

ApplicationEventMulticaster接口是注册监听器和发布事件的抽象接口,AbstractApplicationContext包含其实现类实例作为其属性,使得ApplicationContext容器具有注册监听器和发布事件的能力。在AbstractApplicationContext#refresh方法中,会实例化ApplicationEventMulticaster、注册监听器并发布容器刷新事件ContextRefreshedEvent;在AbstractApplicationContext#doClose方法中,发布容器关闭事件ContextClosedEvent。

support 比较实现类的CustomEvent

这是一种很好的泛型写法,可以运行时反射到(调用方发现是ApplicatonListerner,  使用方可以通过CustomEvent告诉兴趣事件。)

AOP引入

关键概念

Joinpoint,织入点,指需要执行代理操作的某个类的某个方法(仅支持方法级别的JoinPoint);Pointcut是JoinPoint的表述方式,能捕获JoinPoint。

最常用的切点表达式是AspectJ的切点表达式。需要匹配类,定义ClassFilter接口;匹配方法,定义MethodMatcher接口。PointCut需要同时匹配类和方法,包含ClassFilter和MethodMatcher,AspectJExpressionPointcut是支持AspectJ切点表达式的PointCut实现,简单实现仅支持execution函数。

AopProxy是获取代理对象的抽象接口,JdkDynamicAopProxy的基于JDK动态代理的具体实现。TargetSource,被代理对象的封装。MethodInterceptor,方法拦截器,是AOP Alliance的"公民",顾名思义,可以拦截方法,可在被代理执行的方法前后增加代理行为。

JDK实现

Advisor是Pointcut和Advice的组合
public class DynamicProxyTest {@Testpublic void testJdkDynamicProxy() throws Exception {WorldService worldService = new WorldServiceImpl();AdvisedSupport advisedSupport = new AdvisedSupport();TargetSource targetSource = new TargetSource(worldService);WorldServiceInterceptor methodInterceptor = new WorldServiceInterceptor();MethodMatcher methodMatcher = new AspectJExpressionPointcut("execution(* org.springframework.test.service.WorldService.explode(..))").getMethodMatcher();advisedSupport.setTargetSource(targetSource);advisedSupport.setMethodInterceptor(methodInterceptor);advisedSupport.setMethodMatcher(methodMatcher);WorldService proxy = (WorldService) new JdkDynamicAopProxy(advisedSupport).getProxy();proxy.explode();}
}

三级缓存singletonFactories里的对象里面有getObject里面会调用wrapifnessary,在这里会创建新的代理对象,如果二级缓存的话,会存在引用不相等的问题。

	protected Object wrapIfNecessary(Object bean, String beanName) {//避免死循环if (isInfrastructureClass(bean.getClass())) {return bean;}Collection<AspectJExpressionPointcutAdvisor> advisors = beanFactory.getBeansOfType(AspectJExpressionPointcutAdvisor.class).values();try {ProxyFactory proxyFactory = new ProxyFactory();for (AspectJExpressionPointcutAdvisor advisor : advisors) {ClassFilter classFilter = advisor.getPointcut().getClassFilter();if (classFilter.matches(bean.getClass())) {TargetSource targetSource = new TargetSource(bean);proxyFactory.setTargetSource(targetSource);proxyFactory.addAdvisor(advisor);proxyFactory.setMethodMatcher(advisor.getPointcut().getMethodMatcher());}}if (!proxyFactory.getAdvisors().isEmpty()) {return proxyFactory.getProxy();}} catch (Exception ex) {throw new BeansException("Error create proxy bean for: " + beanName, ex);}return bean;}

基于CGLIB的动态代理实现逻辑也比较简单,查看CglibAopProxy。与基于JDK的动态代理在运行期间为接口生成对象的代理对象不同,基于CGLIB的动态代理能在运行期间动态构建字节码的class文件,为类生成子类,因此被代理类不需要继承自任何接口。

public class DynamicProxyTest {private AdvisedSupport advisedSupport;@Beforepublic void setup() {WorldService worldService = new WorldServiceImpl();advisedSupport = new AdvisedSupport();TargetSource targetSource = new TargetSource(worldService);WorldServiceInterceptor methodInterceptor = new WorldServiceInterceptor();MethodMatcher methodMatcher = new AspectJExpressionPointcut("execution(* org.springframework.test.service.WorldService.explode(..))").getMethodMatcher();advisedSupport.setTargetSource(targetSource);advisedSupport.setMethodInterceptor(methodInterceptor);advisedSupport.setMethodMatcher(methodMatcher);}@Testpublic void testCglibDynamicProxy() throws Exception {WorldService proxy = (WorldService) new CglibAopProxy(advisedSupport).getProxy();proxy.explode();}
}
		// 使用JDK动态代理advisedSupport.setProxyTargetClass(false);WorldService proxy = (WorldService) new ProxyFactory(advisedSupport).getProxy();proxy.explode();// 使用CGLIB动态代理advisedSupport.setProxyTargetClass(true);proxy = (WorldService) new ProxyFactory(advisedSupport).getProxy();proxy.explode();

增加AOP代理工厂ProxyFactory,由AdvisedSupport#proxyTargetClass属性决定使用JDK动态代理还是CGLIB动态代理(引用还是一样的)

如果要使用二级缓存解决循环依赖,意味着所有Bean在实例化后就要完成AOP代理,这样违背了Spring设计的原则,Spring在设计之初就是通过AnnotationAwareAspectJAutoProxyCreator这个后置处理器来在Bean生命周期的最后一步来完成AOP代理,而不是在实例化后就立马进行AOP

每层缓存的意义

第三级缓存是个lamdba表达式值捕获bean引用 ,进行advisor判断,然后进行代理升级。

getBeansByType

Application refresh

	@Overridepublic void refresh() throws BeansException {//创建BeanFactory,并加载BeanDefinitionrefreshBeanFactory();ConfigurableListableBeanFactory beanFactory = getBeanFactory();//添加ApplicationContextAwareProcessor,让继承自ApplicationContextAware的bean能感知beanbeanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));//在bean实例化之前,执行BeanFactoryPostProcessorinvokeBeanFactoryPostProcessors(beanFactory);//BeanPostProcessor需要提前与其他bean实例化之前注册registerBeanPostProcessors(beanFactory);//初始化事件发布者initApplicationEventMulticaster();//注册事件监听器registerListeners();//注册类型转换器和提前实例化单例beanfinishBeanFactoryInitialization(beanFactory);//发布容器刷新完成事件finishRefresh();}

//在bean实例化之前,执行BeanFactoryPostProcessor invokeBeanFactoryPostProcessors(beanFactory);

	protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {Map<String, BeanFactoryPostProcessor> beanFactoryPostProcessorMap = beanFactory.getBeansOfType(BeanFactoryPostProcessor.class);for (BeanFactoryPostProcessor beanFactoryPostProcessor : beanFactoryPostProcessorMap.values()) {// 接口的妙用,用接口判断,然后传入beanMap,接口进行处理,和上面泛型接口刚好服务方和调用者做了一个翻转。beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);}}

拓展篇

TODO三级缓存,和

类型转换服务bean

spring在org.springframework.core.convert.converter包中定义了三种类型转换器接口:Converter、ConverterFactory、GenericConverter。

Converter<S,T>接口适合一对一的类型转换,如果要将String类型转换为Ineger/Long/Float/Double/Decimal等类型,就要实现一系列的StringToInteger/StringToLongConverter/StringToFloatConverter转换器,非常不优雅。

ConverterFactory接口则适合一对多的类型转换,可以将一种类型转换为另一种类型及其子类。比如将String类型转换为Ineger/Long/Float/Double/Decimal等Number类型时,只需定义一个ConverterFactory转换器:

做成一个服务的factoryBean

为了方便使用,提供了创建ConversionService的FactoryBean——ConversionServiceFactoryBean。

如果有定义ConversionService,在AbstractApplicationContext#finishBeanFactoryInitialization方法中设置到容器中。

  • 为bean填充属性时,见AbstractAutowireCapableBeanFactory#applyPropertyValues
  • 处理@Value注解时,见AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues

多切面AOP

组装advisor key可以进行缓存,但最好用method作为key

MethodInvocation只是简单的将拦截器链的所有拦截器一一执行,最后再触发当前的method方法。这是很简单高效的方法,但问题是我们希望某些增强比如AfterReturningAdvice能够在方法执行完才被执行,这就涉及到不同增强的执行顺序的问题了。而MethodInvocation显然没有考虑顺序的问题,一个AfterReturningAdvice很可能在BeforeAdvice之前被调用。那么该如何保证顺序问题呢?

答案是,控制增强的调用顺序其实由每个拦截器负责,所以我们需要分析MethodBeforeAdviceInterceptorAfterReturningAdviceInterceptor

但是代理的顺序不同还是会影响返回值,但是相对于一次的方法位置是符合预期的。

三级缓存实现

三级缓存解决问题是解决三个转态转换的状态机(用于单例bean) 1.属性填充完成 2.代理完成对象 3.bean定义(lamdba表达式)

也是一种可重入的判断

也是共享引用的思想

解决有代理对象时的循环依赖问题,需要提前暴露代理对象的引用,而不是暴露实例化后的bean的引用(这是上节的遗留问题的原因,应该提前暴露A的代理对象的引用)。

spring中用singletonFactories(一般称第三级缓存)解决有代理对象时的循环依赖问题。在实例化后提前暴露代理对象的引用(见AbstractAutowireCapableBeanFactory#doCreateBean方法第6行)。

getBean()时依次检查一级缓存singletonObjects、二级缓存earlySingletonObjects和三级缓存singletonFactories中是否包含该bean。如果三级缓存中包含该bean,则挪至二级缓存中,然后直接返回该bean。见AbstractBeanFactory#getBean方法第1行。

protected Object doCreateBean(String beanName, BeanDefinition beanDefinition) {Object bean;try {bean = createBeanInstance(beanDefinition);//为解决循环依赖问题,将实例化后的bean放进缓存中提前暴露if (beanDefinition.isSingleton()) {Object finalBean = bean;addSingletonFactory(beanName, new ObjectFactory<Object>() {@Overridepublic Object getObject() throws BeansException {return getEarlyBeanReference(beanName, beanDefinition, finalBean);}});}//实例化bean之后执行boolean continueWithPropertyPopulation = applyBeanPostProcessorsAfterInstantiation(beanName, bean);if (!continueWithPropertyPopulation) {return bean;}//在设置bean属性之前,允许BeanPostProcessor修改属性值applyBeanPostProcessorsBeforeApplyingPropertyValues(beanName, bean, beanDefinition);//为bean填充属性applyPropertyValues(beanName, bean, beanDefinition);//执行bean的初始化方法和BeanPostProcessor的前置和后置处理方法bean = initializeBean(beanName, bean, beanDefinition);} catch (Exception e) {throw new BeansException("Instantiation of bean failed", e);}//注册有销毁方法的beanregisterDisposableBeanIfNecessary(beanName, bean, beanDefinition);Object exposedObject = bean;if (beanDefinition.isSingleton()) {//如果有代理对象,此处获取代理对象exposedObject = getSingleton(beanName);addSingleton(beanName, exposedObject);}return exposedObject;}

相关文章:

mini-spring源码分析

IOC模块 关键解释 beanFactory&#xff1a;beanFactory是一个hashMap, key为beanName, Value为 beanDefination beanDefination: BeanDefinitionRegistry&#xff0c;BeanDefinition注册表接口&#xff0c;定义注册BeanDefinition的方法 beanReference&#xff1a;增加Bean…...

黑马程序员Java项目实战《苍穹外卖》Day01

苍穹外卖-day01 课程内容 软件开发整体介绍苍穹外卖项目介绍开发环境搭建导入接口文档Swagger 项目整体效果展示&#xff1a; ​ 管理端-外卖商家使用 ​ 用户端-点餐用户使用 当我们完成该项目的学习&#xff0c;可以培养以下能力&#xff1a; 1. 软件开发整体介绍 作为一…...

uniapp开发支付宝小程序自定义tabbar样式异常

解决方案&#xff1a; 这个问题应该是支付宝基础库的问题&#xff0c;除了依赖于官方更新之外&#xff0c;开发者可以利用《自定义 tabBar》曲线救国 也就是创建一个空内容的自定义tabBar&#xff0c;这样即使 tabBar 被渲染出来&#xff0c;但从视觉上也不会有问题 1.官方文…...

python+django5.1+docker实现CICD自动化部署springboot 项目前后端分离vue-element

一、开发环境搭建和配置 # channels是一个用于在Django中实现WebSocket、HTTP/2和其他异步协议的库。 pip install channels#channels-redis是一个用于在Django Channels中使用Redis作为后台存储的库。它可以用于处理#WebSocket连接的持久化和消息传递。 pip install channels…...

python代码示例(读取excel文件,自动播放音频)

目录 python 操作excel 表结构 安装第三方库 代码 自动播放音频 介绍 安装第三方库 代码 python 操作excel 表结构 求出100班同学的平均分 安装第三方库 因为这里的表结构是.xlsx文件,需要使用openpyxl库 如果是.xls格式文件,需要使用xlrd库 pip install openpyxl /…...

【第十课】Rust并发编程(一)

目录 前言 Fork和Join 前言 本节会介绍Rust中的并发编程&#xff0c;并发编程在编程中是提升cpu使用率的一大利器&#xff0c;通过多线程技术提升效率&#xff0c;Rust的并发和其他编程语言的并发不同的地方在于&#xff0c;Rust号称无畏并发。更重要的一点是安全。Rust中所有…...

图形渲染性能优化

variable rate shading conditional render 设置可见性等&#xff0c; 不需要重新build command buffer indirect draw glMultiDraw* - 直接支持多次绘制glMultiDrawIndirect - 间接多次绘制multithreading 多线程录制 实例化渲染 lod texture array 小对象剔除 投影到…...

elasticsearch的索引模版使用方法

5 索引模版⭐️⭐️⭐️⭐️⭐️ 索引模板就是创建索引时要遵循的模板规则索引模板仅对新创建的索引有效&#xff0c;已经创建的索引并不受索引模板的影响 5.1 索引模版的基本使用 1.查看所有的索引模板 GET 10.0.0.91:9200/_index_template2.创建自定义索引模板 xixi &…...

论文学习——进化动态约束多目标优化:测试集和算法

论文题目&#xff1a;Evolutionary Dynamic Constrained Multiobjective Optimization: Test Suite and Algorithm 进化动态约束多目标优化&#xff1a;测试集和算法&#xff08;Guoyu Chen ,YinanGuo , Member, IEEE, Yong Wang , Senior Member, IEEE, Jing Liang , Senior …...

C++中的volatile关键字

作用&#xff1a; 1.它用于修饰变量&#xff0c;告知编译器该变量的值可能会在程序的外部被改变&#xff0c;编译器不能对这个变量的访问进行优化。这是因为编译器通常会对代码进行优化&#xff0c;例如把变量的值缓存到寄存器中&#xff0c;但对于 volatile 变量&#xff0c;…...

linux桌面qt应用程序UI自动化实现之dogtail

1. 前言 Dogtail适用于Linux 系统上进行 GUI 自动化测试,利用 Accessibility 技术与桌面程序通信;Dogtail 包含一个名为 sniff 的组件,这是一个嗅探器,用于 GUI 程序追踪; 源码下载:​​dogtail PyPI 可通过sudo python setup.py install安装或sudo pip install dogt…...

Hello World C#

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System; 引入了System命名空间&#xff0c;基本输入输出。一般只用这个&#xff0c;后面的不用 using System.Collections.Generic; 包含了定…...

SAP开发语言ABAP开发入门

1. 了解ABAP开发环境和基础知识 - ABAP简介 - ABAP&#xff08;Advanced Business Application Programming&#xff09;是SAP系统中的编程语言&#xff0c;主要用于开发企业级的业务应用程序&#xff0c;如财务、物流、人力资源等模块的定制开发。 - 开发环境搭建 - 首先需…...

应急响应靶机——easy溯源

载入虚拟机&#xff0c;开启虚拟机&#xff1a; &#xff08;账户密码&#xff1a;zgsfsys/zgsfsys&#xff09; 解题程序.exe是额外下载解压得到的&#xff1a; 1. 攻击者内网跳板机IP地址 2. 攻击者服务器地址 3. 存在漏洞的服务(提示:7个字符) 4. 攻击者留下的flag(格式…...

【前端】vscode报错: 无法加载文件 D:\nodejs\node_global\yarn.ps1,因为在此系统上禁止运行脚本。

vscode运行前端代码时候&#xff0c;执行yarn install时候报错 问题&#xff1a; 无法加载文件 D:\nodejs\node_global\yarn.ps1&#xff0c;因为在此系统上禁止运行脚本。 解决方式&#xff1a; 首先用管理员身份运行vscode 查看 get-ExecutionPolicy&#xff0c;Restrict…...

Spring Web MVC(详解中)

文章目录 Spring MVC&#xff08;中&#xff09;RESTFul风格设计RESTFul风格概述RESTFul风格特点RESTFul风格设计规范RESTFul风格好处RESTFul风格实战需求分析RESTFul风格接口设计后台接口实现 基于RESTFul风格练习&#xff08;前后端分离模式&#xff09;案例功能和接口分析功…...

Flutter:encrypt插件 AES加密处理

1、pubspec.yaml导入插件 cupertino_icons: ^1.0.8 # 密码加密 encrypt: 5.0.3encrypt封装 import package:encrypt/encrypt.dart; /// 加密类 class EncryptUtil {static final EncryptUtil _instance EncryptUtil._internal();factory EncryptUtil() > _instance;Encrypt…...

Python bytes类型及用法

在Python中&#xff0c;bytes类型是一种不可变的字节序列&#xff0c;用于存储原始的二进制数据。bytes对象通常用于处理文件、网络通信和其他需要处理原始字节数据的场景。 以下是bytes类型的一些基本用法和特性&#xff1a; 1. 创建bytes对象 可以通过多种方式创建bytes对…...

阅读《基于蒙特卡洛法的破片打击无人机易损性分析》_笔记

目录 基本信息 1 引言 1.1 主要研究内容 1.2 研究必要性&#xff08;为什么要研究&#xff09; 1.3 该领域研究现状&#xff08;别人做了什么/怎么做的&#xff09; 2 主要研究过程&#xff08;我们做了什么&#xff09; 2.1 建立目标仿真模型 2.2 确定毁伤依据 2.3 无…...

【vim】vim怎么把某一列内容复制到另一列

1. vim 怎么把某一列内容复制到另一列 移动光标到你想复制的列的第一个字符上。按下 ctrlv 进入选择模式。按下方向键选择多行。按下 h 或 j 或 k 或 l&#xff0c;选择整列。按下 y 复制所选择的列。移动光标到你想粘贴内容的列的第一个字符上。按下 p 粘贴内容。...

进程地址空间(比特课总结)

一、进程地址空间 1. 环境变量 1 &#xff09;⽤户级环境变量与系统级环境变量 全局属性&#xff1a;环境变量具有全局属性&#xff0c;会被⼦进程继承。例如当bash启动⼦进程时&#xff0c;环 境变量会⾃动传递给⼦进程。 本地变量限制&#xff1a;本地变量只在当前进程(ba…...

css实现圆环展示百分比,根据值动态展示所占比例

代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...

React Native 导航系统实战(React Navigation)

导航系统实战&#xff08;React Navigation&#xff09; React Navigation 是 React Native 应用中最常用的导航库之一&#xff0c;它提供了多种导航模式&#xff0c;如堆栈导航&#xff08;Stack Navigator&#xff09;、标签导航&#xff08;Tab Navigator&#xff09;和抽屉…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来

一、破局&#xff1a;PCB行业的时代之问 在数字经济蓬勃发展的浪潮中&#xff0c;PCB&#xff08;印制电路板&#xff09;作为 “电子产品之母”&#xff0c;其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透&#xff0c;PCB行业面临着前所未有的挑战与机遇。产品迭代…...

Debian系统简介

目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版&#xff…...

【算法训练营Day07】字符串part1

文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接&#xff1a;344. 反转字符串 双指针法&#xff0c;两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...

镜像里切换为普通用户

如果你登录远程虚拟机默认就是 root 用户&#xff0c;但你不希望用 root 权限运行 ns-3&#xff08;这是对的&#xff0c;ns3 工具会拒绝 root&#xff09;&#xff0c;你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案&#xff1a;创建非 roo…...

现代密码学 | 椭圆曲线密码学—附py代码

Elliptic Curve Cryptography 椭圆曲线密码学&#xff08;ECC&#xff09;是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础&#xff0c;例如椭圆曲线数字签…...

【git】把本地更改提交远程新分支feature_g

创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...

BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践

6月5日&#xff0c;2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席&#xff0c;并作《智能体在安全领域的应用实践》主题演讲&#xff0c;分享了在智能体在安全领域的突破性实践。他指出&#xff0c;百度通过将安全能力…...