Java技术整理(5)—— Spring篇
Spring是一个全面的全面的、企业应用开发一站式的解决方案,贯穿表现层、业务层、持久层。但是 Spring 仍然可以和其他的框架无缝整合。
1、Spring的核心组件
(1)数据层: JDBC、ORM、OXM、JMS、Transations
(2)Web层: Web、Servlet、Portlet、Struts
(3)中间层: AOP、Aspects、Instrumentation
(4)核心容器: Beans、Core、Context、Expression Language
(5)测试层: Test
2、Spring IOC 原理
(1)概念: Spring通过一个配置文件描述Bean及Bean之间的依赖关系,利用Java语言的反射功能实例化 Bean并建立Bean之间的依赖关系。Spring的IOC容器在完成这些底层工作的基础上,还提供 了 Bean实例缓存、生命周期管理、Bean实例代理、事件发布、资源装载等高级服务。
(2)Spring容器高层视图
- Spring启动时读取应用程序提供的Bean配置信息,并在Spring容器中生成一份相应的Bean配置注册表
- 根据这张注册表实例化Bean,并将Bean实例存入Bean缓存池
- 应用程序读取Bean缓存池中的Bean实例
(3)IOC容器实现
IOC容器依赖于BeanFactory,是Spring框架的基础程序,所以开发者操作的是ApplicationContext而非底层的BeanFactory。
Bean注册表
首先,Spring配置文件中的每一个节点元素在Spring容器中都通过一个 BeanDefinition 对象表示,它表述了 Bean 的配置信息,而BeanDefinitionRegistry 接口提供了向容器手动注册 BeanDefinition 对象的方法。
获取Bean实例对象
BeanFactory 提供的最主要方法就是getBean(String beanName)
方法,调用该方法能从容器中返回一个特定名称的Bean。
访问容器中关于Bean的基本信息——ListableBeanFactory
BeanFactory 的子类 ListableBeanFactory,提供了访问容器内关于Bean 的基本信息,如Bean的个数,获取某一类型Bean的配置名、查看容器中是否包含某一Bean等方法。
父子级容器——HierarchicalBeanFactory
父子级联IOC容器实现的接口是HierarchicalBeanFactory
,子容器可以通过接口方法访问父容器,由此建立的IOC级联容器体系中,子容器可以访问父容器,而父容器无法访问子容器。
Spring利用父子级联容器实现了很多功能,例如 SpringMVC中,View层的Bean位于一个子容器中,而Service层和Dao层的Bean位于父容器中,这样View层的Bean就可以引用Service层和Dao层的Bean了
拓展接口 —— ConfigurableBeanFactory
这是一个BeanFactory子类系列十分重要的接口,它增强了IOC的可定制性,它定义了设置类加载器、属性编辑器、容器初始化后置处理器等方法
自动装配——AutowireCapableBeanFactory
这个接口定义了容器中的Bean按某种规则(如按名字匹配、按类型匹配等)进行自动装配的方法。
注册单例Bean——SingletonBeanRegistry
这个接口定义了允许在运行期间向容器注册单例Bean的方法。
对于单例Bean对象来说,BeanFactory会缓存Bean实例,所以第二次调用getBean()获取Bean对象时会直接从IOC容器的缓存中获取Bean实例。
Spring 在 DefaultSingletenBeanFactory 类中提供了用于缓存单例Bean 缓存器,这个缓存器使用HashMap实现,单例Bena以beanName作为key进行存储。
BeanFactory依赖日志框架
在初始化 BeanFactory 时,必须提供一种日志框架,例如使用Log4j,这样启动Spring容器时才不会报错。
BeanFactory提供给开发者的操作类——ApplicationContext
ApplicationContext 继承于 HierarchicalBeanFactory 和 ListableBeanFactory 接口,并由此拓展出其它功能接口:
- ClassPathXmlApplicationContext: 默认从类路径加载配置文件
- FileSystemXmlApplicationContext: 默认从文件系统中装载配置文件
- ApplicationEventPublisher: 让容器拥有发布应用上下文事件的功能,包括启动容器事件、关闭容器事件等
- MessageSource: 为应用提供 il8n 国际化消息访问的功能
- ResourcePatternResolver: 通过带前缀的Ant风格的资源文件路径装载Spring配置条件
- LifeCycle: 这个接口是Spring 2.0 时加入的,提供了start 和 stop 方法,主要用来控制异步处理过程,在具体使用中,该接口会被ApplicaitonContext和Bean实例同时实现,ApplicationContext 会将 start 和 stop 状态发布给所有实现了接口的Bean,以达到管理和控制JMX、任务调度的目的
- ConfigurableApplicationContext: 扩展了ApplicationContext,主要是新增了两个方法:refresh() 和 close(),让ApplicationContext拥有了启动、刷新、关闭应用上下文的功能。
WebApplicationContext
WebApplicationContext是专门为Web应用准备的,它允许从相对于Web根目录的路径中装载配置文件完成初始化工作,从WebApplicationContext中可以获得ServletContext的引用,整个Web应用上下文对象将作为属性放置到ServletContext 中,以便Web应用环境可以访问Spring应用上下文。
(4)Spring Bean的作用域
Spring 3.0 定义了五种Bean的作用域:单例、原型、请求、会话、全局会话
- singleton(单例模式,多线程不安全): Spring IOC容器只存在一个共享的 Bean 实例,无论有多少个 Bean 引用它,始终指向同一个对象,但这种模式在多线程环境下是不安全的。
- prototype(原型模式): Spring 每一次尝试获取原型模式的Bean对象时,容器都将创建一个新的Bean提供给Spring。
- request(请求模式): 一次HTTP请求,Spring创建一次新的Bean提供使用,其生命周期随请求状态的销毁而销毁。
- session(会话模式): 一次Http Session 中,容器返回的是同一个实例,当重新开启一次Http Session,容器会重新创建一个Bean实例提供使用,请求结束,实例销毁。
- global session(全局会话模式): 在一个全局Http Session中,容器返回同一个Bean实例,仅在protlet context时使用。
(5)Spring Bean的生命周期
SpringBean的生命周期:实例化 —— 属性赋值 —— 初始化 —— 销毁
实例化: 实例化一个Bean,也就是我们常说的new
属性赋值
- IOC 依赖注入: 按照Spring Context对Bean实例进行配置
- setBeanName的实现: 若Bean实现了
BeanNameAware
接口,调用setBeanName(String beanId)
方法 - setBeanFactory的实现: 若Bean实现了
BeanFactoryAware
接口,调用setBeanFactory(BeanFacrtory beanFactory)
方法 - setApplicationContext的实现: 若Bean实现了
ApplicationContextAware
接口,调用setApplicationContext(ApplicationContext applicationContext)
方法,可以实现设置BeanFactory方法,并比BeanFactoryAware更加优秀 - postProcessBeforelnitialization的实现: 若Bean实现了
BeanPostProcessor
接口,将调用postProcessBeforelnitialization(Object obj, String s)
方法,BeanPostProcessor经常用于Bean内容的修改,并且Bean初始化结束后也会调用这个方法,也可以应用于内存或缓存技术。
初始化
- init-method: 若Bean在配置文件中定义了初始化方法,则在初始化阶段会自动调用配置的初始化方法。
- postProcessAfterInitialization的实现: 若Bean实现了
BeanPostProcessor
接口,调用postProcessAfterInitialization(Object obj, String s)
方法。
销毁
- destroy 过期自动清理阶段: 当Bean不再需要时,会经历清理阶段,若 Bean 实现了 DisposableBean 接口,则调用
destroy()
方法进行销毁。 - destroy-method 自配置清理: 若Bean的配置文件中设置了destroy方法时,则自动调用自定义的destroy方法
(6)Spring 依赖注入的方式
Spring 提供的依赖注入的方式:构造器注入、set方法注入、静态工厂注入、实例工厂注入
构造器注入案例
public CatDaoImpl(String message){this.message = message;
}<bean id="CatDaoImpl" class="class.CatDaoImpl"><constructor-arg value="message"></constructor-arg>
</bean>
setter方法注入
public class Id{private int id;public int getId(){return id;}public void setId(int id){this.id = id;}
}<bean id="id" class="com.Id"><property name="id" value="123"></property>
</bean>
静态工厂注入
// 对外提供的静态工厂
public class DaoFactory{public static final FactoryDao getStaticFactoryDaoImpl(){return new StaticFactoryDaoImpl;}
}//使用静态工厂的类
public class SpringAction{//注入对象private DaoFactory staticFactoryDao;//注入对象的set方法public void setStaticFactoryDao(FactoryDao staticFactoryDao){this.staticFactoryDao = staticFactoryDao;}
}//给调用类注入静态工厂
<bean name="springAction" class="com.SpringAction"><property name="staticFactoryDao" ref="staticFatoryDao"></property>
</bean>//给静态工厂中的成员注入
<bean name="staticFatoryDao" class="com.DaoFactory" factory-method="getStaticFactoryDaoImpl"></bean>
实例工厂注入
//创建一个实例工厂
public class DaoFactory{public DaoFactory getFactoryDaoImpl(){return new FactoryDaoImpl(); }
}//调用类使用实例工厂
public class SpringAction{private DaoFactory daoFactory;public void setDaoFactory(DaoFactory daoFactory){this.daoFactory = daoFactory;}
}//为调用类注入实例工厂Bean对象
<bean name="springAction" class="SpringAction"><property name="daoFactory" ref="daoFactory"></property>
</bean>//管理实例工厂,先声明注入的类,再配置实例工厂的成员
<bean name="daoFactory" class="com.DaoFactory"></bean>
<bean name="factoryDao" factory-bean="daoFactory" factory-method="getFactoryDaoImpl"></bean>
(7)自动装配的实现方式
Spring装配包括手动装配和自动装配,手动装配是基于 xml 装配、构造方法、setter方法等。
自动装配一共有5种实现方式:
- no: 默认不自动装配,通过显式的 ref 属性进行装配
- byName: 通过参数名自动装配,Spring在配置文件中检测到Autowired属性被设置为byName,容器自动按照beanName进行注入
- byType: 通过参数类型自动装配,Spring在配置文件中检测到Autowired属性被设置为byType,容器自动按照type进行注入,若有多个匹配对象,则抛出错误
- constructor: 类似于byType,但必须提供构造器参数,若没有确定参数的构造器参数类型,则抛出异常
- autodetect: 首先尝试使用 构造器参数 装配,若无法工作则使用byType方式
3、Spring AOP 的原理
(1)概念: AOP是一种“横切”技术,将多个类的公共模块抽取到一个模块中,并将其命名为**“Aspect”**,即切面。
(2)AOP的两个部分: 核心关注点、横切关注点
- 核心关注点: 业务处理的主要流程
- 横切关注点: 一切与业务代码无相关的代码
(3)AOP的应用场景:
- Authentication: 权限
- Caching: 缓存
- Context passing: 内容传递
- Error handling: 错误处理
- Lazy loading: 懒加载
- Debugging: 调试
- logging, tracing, profiling and monitoring: 记录跟踪 优化 校准
- Performance optimization: 性能优化
- Persistence: 持久化
- Resource pooling: 资源池
- Synchronization: 同步
- Transactions: 事务
(4)AOP的核心概念:
- 切面(Aspect): 类是对物体特征的抽象,切面是对横切关注点的抽象
- 横切关注点: 对哪些对象进行拦截、如何处理,这些关注点都是横切关注点
- 连接点(JoinPoint): 被拦截到的点,因为Spirng只支持方法类型的连接点,所以Spirng中连接点就是被拦截方法,实际上连接点还可以是字段、构造方法
- 切入点(PointCut): 对连接点进行拦截的定义
- 通知(Advice): 所谓的通知就是拦截到连接点后要执行的代码,分为前置、后置、异常、最终、环绕通知等类型
- 目标对象: 代理的目标对象
- 织入(weave): 将切面应用到目标对象并导致代理对象创建的过程
- 引入(introduction): 不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段
(5)AOP的代理方式
Spring 提供了两种AOP的代理方式:JDK接口动态代理、CGLib动态代理
JDK接口动态代理:
- 被代理类实现
InvocationHandler
,通过实现该接口定义横切逻辑,并通过反射机制调用目标类的代码,动态地将横切逻辑和业务逻辑编织在一起 - 代理类通过
InvocationHandler
接口动态创建一个实例,生成目标类的代理对象
GCLib动态代理:
GCLib的全称是Code Generation Library,是一个高性能、高质量的代码生成类库,可以在运行期间动态扩展Java类和实现Java接口,CGLib封装了ASM,可以在运行期间生成新的class,对比JDK动态代理,CGLib可以动态代理未实现接口的类。
(6)AOP的实现原理
@Aspect
public class TransactionDemo {@Pointcut(value="execution(* com.yangxin.core.service.*.*.*(..))") public void point(){}@Before(value="point()")public void before(){System.out.println("transaction begin");}@AfterReturning(value = "point()")public void after(){System.out.println("transaction commit");}@Around("point()")public void around(ProceedingJoinPoint joinPoint) throws Throwable{ System.out.println("transaction begin");joinPoint.proceed();System.out.println("transaction commit");}
}
4、Spring MVC 的原理
MVC指的是Modal(模型),View(视图),Controller(控制器),Spring MVC框架是围绕 DispatcherServlet 而设计的,这个Servlet会将请求分发到各个控制器,并支持可配置的处理器映射、视图渲染、本地化、时区与主题渲染等,甚至还能支持文件上传。
(1)浏览器请求的全过程:
- 浏览器发送HTTP请求,DispatcherServlet接收
- DispatcherServlet轮询处理器,通过HandlerMapping进行查找适用的Controller
- 当HandlerMapping查找到处理器后,DispatcherServlet调用处理器,将请求发送给Controller
- Controller调用Service层业务逻辑,获取返回值后分发到ModalAndView对象
- DispatcherServlet监听ModalAndView响应结果
- DispatcherServlet得到结果后分发给Model对象,并轮询视图映射ViewResolver,查找到指定的视图
- Modal将结果反应到视图,View向浏览器发送响应体
(2)MVC常用注解
组件注解: @Controller、@RestController、@Component、@Repository、@Service
请求注解: @RequestMapping、@Autowired、@PathVariable、@RequestParam、@RequestHeader
5、MyBatis缓存
MyBatis拥有两级缓存,默认情况下开启一级缓存,二级缓存由开发者手动开启。
一级缓存是会话级别的缓存,当同一会话调用同一个SQL时,优先从缓存中读取数据。
二级缓存是映射级别的缓存,不同的SQL会话可以共享该缓存
(1)一级缓存的原理
当用户线程第一次发出查询sql,sql的查询结果会写入到sqlSession的一级缓存中,缓存使用的是Map结构,其中key = mapperID + offset + limit + SQL + 所有入参,value = 用户信息
,当同一个sqlSession再次发出同一个sql请求,就从缓存中取出数据,若两次查询中间发生更新操作,则本sqlSession中的一级缓存区域全部清空,所以第二次请求会从数据库中查询,并写入到新的缓存中去。
(2)二级缓存的原理
二级缓存的范围是mapper同命名空间的mapper,mapper以命名空间为单位创建缓存数据结构,结构是 map,通过 CacheExecutor 实现的。
CacheExecutor是Executor的代理对象,所有的查询操作,在CacheExecutor都会先查询缓存,再查询数据库。
(3)如何配置二级缓存
- MyBatis 全局配置中启用二级缓存配置
- 对应的mapper配置cache节点
- 对应的select查询节点添加useCache=true
相关文章:
Java技术整理(5)—— Spring篇
Spring是一个全面的全面的、企业应用开发一站式的解决方案,贯穿表现层、业务层、持久层。但是 Spring 仍然可以和其他的框架无缝整合。 1、Spring的核心组件 (1)数据层: JDBC、ORM、OXM、JMS、Transations (2&#x…...
07-MySQL-基础篇-函数
函数之字符串函数 前言函数字符串函数数值函数日期函数流程函数 前言 本篇来学习下MySQL中的函数–字符串函数。 函数 函数:是指一段可以直接被另一段程序调用的程序或代码MySQL中的函数主要分为以下四类: 字符串函数、数值函数、日期函数、流程函数。…...

不同路径 II——力扣63
class Solution {public:int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {int n=...

NLP文本分类
NLP文本分类 落地实战五大利器!_kaiyuan_sjtu的博客-CSDN博客https://zhuanlan.zhihu.com/p/432619164 https://github.com/alibaba/EasyNLP/blob/master/README.cn.md...
进程和线程的联系与区别
文章目录 一、进程和线程的联系二、进程和线程的区别 一、进程和线程的联系 操作系统中可以有很多进程,每个进程都有自己独立的资源;一个进程中可以有很多线程,系统中的每个线程都能独立调度,同一个进程中的各个线程共享内存/硬盘…...

分支和循环语句(2)(C语言)
目录 do...while()循环 do语句的语法 do语句的特点 do while循环中的break和continue 练习 goto语句 do...while()循环 do语句的语法 do 循环语句; while(表达式); do语句的特点 循环至少执行一次,使用的场景有限,所以不是经常使用。 #inc…...
Flutter: A RenderFlex overflowed by 42 pixels on the bottom.
Flutter:渲染活动底部上方溢出了42个像素 Flutter 控件超出异常:A RenderFlex overflowed by 42 pixels on the bottom. 解决方案 1.Scaffold内添加 resizeToAvoidBottomInset 属性,缺点是软键盘下面的控件被挡住 Scaffold( resizeToAvoidBot…...

第三章,矩阵,07-用初等变换求逆矩阵、矩阵的LU分解
第三章,矩阵,07-用初等变换求逆矩阵、矩阵的LU分解 一个基本的方法求 A − 1 B A^{-1}B A−1BLU分解例1,求矩阵A的LU分解:例12,LU分解解线性方程组: 玩转线性代数(19)初等矩阵与初等变换的相关应用的笔记&a…...

STM32F429IGT6使用CubeMX配置SPI通信(W25Q256芯片)
1、硬件电路 需要系统性的看一下W25Q256芯片手册 2、设置RCC,选择高速外部时钟HSE,时钟设置为180MHz 3、配置SPI 4、生成工程配置 5、相关代码 #define sFLASH_ID 0XEF4019 // W25Q256#define SPI_FLASH_PageSize 256 #define SPI_FLASH_PerWritePageSize 256#def…...
C++11异步与通信之 packaged_task
概念简介 packaged_task 用于包装可调用目标(Callable)为一个对象,如lambda,普通函数,小括号重载等,用于异步调用。 其返回值或所抛异常被存储于能通过 std::future 对象访问的共享状态中,和promise类似。 将函数的调用与函数返…...

磁盘的管理
一、磁盘的分区 查看磁盘 lsblk fdisk -l 2、分区 没有e扩展,则都是主分区,已经有三个主分区了,剩下的全设置为扩展 查看分区结果: 二、格式化 三、挂载...
数据结构:完全二叉树的性质
完全二叉树的性质: 具有 n n n个结点的完全二叉树的深度为 [ l o g 2 n ] 1 ( [ x ] 表示不大于 x 的最大整数 ) [log_2n]1([x]表示不大于x的最大整数) [log2n]1([x]表示不大于x的最大整数) 对于任意一个结点 ( 1 < i < n ) &…...

【数据结构】‘双向链表’冲冲冲
💐 🌸 🌷 🍀 🌹 🌻 🌺 🍁 🍃 🍂 🌿 🍄🍝 🍛 🍤 📃个人主页 :阿然成长日记 …...

Linux 编译CEF源码详细记录
Linux CEF(Chromium Embedded Framework)源码下载编译 背景 由于CEF默认的二进制分发包不支持音视频播放,需要自行编译源码,将ffmpeg开关打开才能支持。这里介绍的是Linux平台下的CEF源码下载编译过程。 Windows平台参考&#…...
LeetCode 2810. Faulty Keyboard【模拟,双端队列,字符串】简单
本文属于「征服LeetCode」系列文章之一,这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁,本系列将至少持续到刷完所有无锁题之日为止;由于LeetCode还在不断地创建新题,本系列的终止日期可能是永远。在这一系列刷题文章…...

两个数组的交集-C语言/Java
描述 给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序。(1 < nums1.length, nums2.length < 1000,0 < nums1[i], nums2[i] < 1000) 示例1 输入…...

Arduino+esp32学习笔记
学习目标: 使用Arduino配置好蓝牙或者wifi模块 学习使用python配置好蓝牙或者wifi模块 学习内容(笔记): 一、 Arduino语法基础 Arduino语法是基于C的语法,C又是c基础上增加了面向对象思想等进阶语言。那就只记录没见过的。 单多…...

计算机网络-专业术语
计算机网络-专业术语 实体 实体:任何可发送或接收信息的硬件或软件进程 对等实体:收发双方相同层次中的实体 协议 控制两个对等实体进行逻辑通信的规则的集合 协议三要素 语法 定义所交换的信息的格式 是用户数据与控制信息的结构和格式 语义 定义收发双方所需要完成的操作…...
E. Maximum Monogonosity
You are given an array aa of length nn and an array bb of length nn. The cost of a segment [l,r][l,r], 1≤l≤r≤n1≤l≤r≤n, is defined as |bl−ar||br−al||bl−ar||br−al|. Recall that two segments [l1,r1][l1,r1], 1≤l1≤r1≤n1≤l1≤r1≤n, and [l2,r2][l2,…...
已解决Excel file format cannot be determined, you must specify an engine manually
问题 我使用以下语句时出现错误 data pd.read_excel(temp_inputc.csv, headerNone)出现错误: Excel file format cannot be determined, you must specify an engine manually有很多人说添加engine,但接下来会出现这个错误: File is not…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序
一、开发准备 环境搭建: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 项目创建: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...

【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...
反射获取方法和属性
Java反射获取方法 在Java中,反射(Reflection)是一种强大的机制,允许程序在运行时访问和操作类的内部属性和方法。通过反射,可以动态地创建对象、调用方法、改变属性值,这在很多Java框架中如Spring和Hiberna…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...