【七】springboot启动源码 - finishBeanFactoryInitialization

finishBeanFactoryInitialization 源码解析

Instantiate all remaining (non-lazy-init) singletons.
初始化剩下非懒加载的实例对象

finishBeanFactoryInitialization方法第918行,beanFactory.preInstantiateSingletons();
在这里插入图片描述
preInstantiateSingletons方法,遍历beanDefinitionNames,通过mergedBeanDefinitions来获取每一个RootBeanDefinition,并判断他是否是factorybean,如果不是,调用getBean()方法。如果是,看到后面的FactoryBean部分

在这里插入图片描述
doGetBean方法
第252行,transformedBeanName(name),用于返回真实beanName,如果是beanName以&开头(表示factoryBean),去掉&并返回。通过Map<String, String> aliasMap来获取该beanName是否为别名,如果key有值,返回value
在这里插入图片描述
第256行,getSingleton(beanName),通过singletonObjects来获取之前是否已经注入到IOC中

Eagerly check singleton cache for manually registered singletons.

在这里面做了三级缓存,也是spring解决循环依赖的地方,在后面分析
这里做调试的类没有进行过初始化,singletonObjects返回null
在这里插入图片描述
AbstractBeanFactory第300行,typeCheckOnly一般都为false(用于类型检查实例是否获得,而不是实际使用)
进入markBeanAsCreated方法
判断alreadyCreated(已标记为创建)是否包含beanName,这里通过双重校验锁,如果不包含,将beanName添加到alreadyCreated
在这里插入图片描述
clearMergedBeanDefinition方法,将bd的stale设置为true,并从mergedBeanDefinitionHolders移除beanName
在这里插入图片描述
AbstractBeanFactory第309行,getMergedLocalBeanDefinition方法
在这里插入图片描述
进入getMergedLocalBeanDefinition方法
从mergedBeanDefinitions取出beanName对应的RootBeanDefinition
在这里插入图片描述
回到AbstractBeanFactory,判断类是否有@DependsOn注解
第332行,开始创建对象实例
在这里插入图片描述

getSingleton.getObject()

进入getSingleton方法
通过双重校验再次判断singletonObjects是否存在beanName
第234行,开始调用ObjectFactory(类似Supplier)的getObject方法
在这里插入图片描述
在这里插入图片描述
第514行,resolveBeanClass,解析beanClass,如果是对象被代理,返回代理对象的class
在这里插入图片描述
第531行,resolveBeforeInstantiation,如果有自定义InstantiationAwareBeanPostProcessor实现,调用postProcessBeforeInstantiation(实例化之前执行)。可以实例化自定义bean,但是这个回调会在所有bean实例化的时候都执行。非自定义的类也会在这里实例化,会有不可预估的风险,如果方法返回的不为null,表示已经实例化,直接返回这个bean作为创建的单例对象,并注册到IOC容器。

Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.

在这里插入图片描述
第542行,doCreateBean,正式开始实例化bean
在这里插入图片描述

doCreateBean

第582行,进入createBeanInstance
在这里插入图片描述

createBeanInstance

determineConstructorsFromBeanPostProcessors,在这里回调SmartInstantiationAwareBeanPostProcessor的determineCandidateConstructors方法,可以用来设置类的自定义构造器

在这里插入图片描述
instantiateBean方法,通过默认无参构造来实例化bean
在这里插入图片描述
进入instantiateBean方法,第1326行。beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
通过实例化策略执行器开始实例化bean,主要还是通过构造器实例化,过程略。
返回实例对象后,封装成BeanWrapper并返回
在这里插入图片描述

applyMergedBeanDefinitionPostProcessors

实例化bean之后,第594行,applyMergedBeanDefinitionPostProcessors方法。会在这里回调MergedBeanDefinitionPostProcessor接口postProcessMergedBeanDefinition方法
在这里插入图片描述

populateBean

在这里插入图片描述

InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation回调

进入populateBean方法,第1399行,回调InstantiationAwareBeanPostProcessor接口的postProcessAfterInstantiation。用于自定义判断bean与beanName是否满足相同预期结果
在这里插入图片描述

InstantiationAwareBeanPostProcessor的postProcessProperties回调

第1431行,回调InstantiationAwareBeanPostProcessor接口的postProcessProperties方法
在这里插入图片描述

AutowiredAnnotationBeanPostProcessor(@Autowire依赖处理)

spring的实现类AutowiredAnnotationBeanPostProcessor,这里会根据进行@Autowire注解的依赖注入,会实例化依赖的类
在这里插入图片描述
在这里插入图片描述

CommonAnnotationBeanPostProcessor(@Resource依赖处理)

或者如果使用的@Resource注解,会通过CommonAnnotationBeanPostProcessor类来实例化类
在这里插入图片描述
在这里插入图片描述

以上两种注入方式,都会通过beanFactory.getBean(beanName);来实例化依赖类,如果依赖为接口,需要找实现接口的类并实例化,如果是类直接进行实例化

initializeBean

在这里插入图片描述
进入initializeBean,第1791行,invokeAwareMethods

invokeAwareMethods

在这里插入图片描述
判断bean是否实现Aware,如果当前对象是cglib生成的代理对象,默认实现EnhancedConfiguration接口,该接口继承了BeanFactoryAware
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
把beanFactory设置到bean中
在这里插入图片描述
在这里插入图片描述

BeanPostProcessor的postProcessBeforeInitialization回调

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

CommonAnnotationBeanPostProcessor

由父类InitDestroyAnnotationBeanPostProcessor执行postProcessBeforeInitialization,会触发bean的@PostConstruct注解方法(充当init-method)
在这里插入图片描述

ConfigurationPropertiesBindingPostProcessor回调

ConfigurationPropertiesBindingPostProcessor的postProcessBeforeInitialization,会执行@ConfigurationProperties的自定绑定model字段逻辑。
在这里插入图片描述
判断类上是否有@ConfigurationProperties,并创建ConfigurationPropertiesBean返回
在这里插入图片描述
在这里插入图片描述
获取待绑定的字段,从PropertySource中寻找该字段对应的值(PropertySource值在之前已经缓存)
在这里插入图片描述
最终通过JavaBeanBinder的setValue方法,来为字段赋值
在这里插入图片描述

invokeInitMethods

在这里插入图片描述

InitializingBean的afterPropertiesSet回调

在这里插入图片描述

@Bean(initMethod = “doInit”)回调doInit

如果对象有初始化方法(在其他配置类中定义的@Bean(initMethod = “doInit”)),会进行调用
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

BeanPostProcessor的postProcessAfterInitialization回调

在这里插入图片描述

AnnotationAwareAspectJAutoProxyCreator(创建AOP代理)

创建AOP代理,详细分析看下面AOP章节

getSingleton

上面已经将对象实例化。
第633行,getSingleton方法。
在这里插入图片描述

registerDisposableBeanIfNecessary

第661行,registerDisposableBeanIfNecessary方法。
待补充

addSingleton(beanName, singletonObject)

注册单例对象到IOC容器
在这里插入图片描述

SmartInitializingSingleton回调

遍历所有容器单例对象,判断是否实现SmartInitializingSingleton,如果实现会调用afterSingletonsInstantiated方法
在这里插入图片描述
至此finishBeanFactoryInitialization结束

循环依赖的处理

前提:开启允许循环依赖,springboot 2.6 之后就默认关闭了。
A(cicA)与B(cicB)相互依赖,A先进行初始化

  1. A完成bean实例创建
    在这里插入图片描述

  2. 判断是否开启了循环依赖,并添加A的bean实例工厂到beanFactory的singletonFactories中(作为第三级缓存)
    在这里插入图片描述

  3. 在populateBean方法中,回调InstantiationAwareBeanPostProcessor的postProcessProperties方法。这里我们需要关注AutowiredAnnotationBeanPostProcessor类。执行依赖注入
    在这里插入图片描述
    通过A上被@Autowire修饰的成员变量,获取到待注入的类(这里的cicB是与当前类互为循环依赖的),封装成InjectedElement
    在这里插入图片描述
    遍历这两个InjectedElement,依次进行解析,并调用beanFactory.getBean(beanName)。这里的bean是cicB
    在这里插入图片描述

  4. B完成bean实例创建,和A的第1步一样

  5. 添加B的bean实例工厂到beanFactory的singletonFactories中,和A的第2步一样

  6. 依然通过AutowiredAnnotationBeanPostProcessor的postProcessProperties方法,获取B下的被@Autowire修饰的成员变量,来执行依赖注入
    在这里插入图片描述
    和A的第3步一样,调用beanFactory.getBean(beanName)。这里的bean是cicA
    来到doGetBean的getSingleton(beanName)方法,从这里尝试获取A的对象
    a. 首先从一级缓存singletonObjects获取bean,因为A对象只是实例化,还没有初始化,因此还没有注入到singletonObjects中
    在这里插入图片描述
    b.一级缓存中获取不到bean,从二级缓存earlySingletonObjects获取,此时二级缓存也没有A的对象
    在这里插入图片描述
    c. 这里通过双重校验锁再次确保一、二级缓存都不存在bean。从三级缓存singletonFactories中获取到对象的ObjectFactory,通过执行ObjectFactory.getObject方法。调用如下的函数式接口,beanName为cicA,bean为实例化之后的cicA对象,返回该对象
    在这里插入图片描述
    这里会调用SmartInstantiationAwareBeanPostProcessor的getEarlyBeanReference方法
    在这里插入图片描述
    返回cicA对象,将对象放入二级缓存earlySingletonObjects中
    在这里插入图片描述
    获取到cicA之后,通过Field将cicA设置到cicB的字段中
    在这里插入图片描述

  7. cicB完成初始化,注册到一级缓存,从二、三级缓存删除

  8. 返回cicB,通过Field将cicB设置到cicA的字段中
    在这里插入图片描述

  9. cicA完成初始化,注册到一级缓存,从二、三级缓存删除
    在这里插入图片描述

总结

在这里插入图片描述

FactoryBean

用于创建比较复杂的bean
比如从配置文件中获取配置,通过不同值来生成不同bean

自定义FactoryBean

package org.hopehomi.boot.model.factorybean;import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.SmartFactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;/*** @author Ledison* @date 2023/3/19*/
@Component
@Slf4j
@Data
public class MyFactoryBean implements SmartFactoryBean<Human>, InitializingBean, DisposableBean {private Human human;@Autowiredprivate Environment environment;public MyFactoryBean() {System.out.println("MyFactoryBean construct");}@Overridepublic boolean isEagerInit() {return true;}@Overridepublic void afterPropertiesSet() throws Exception {String sex = environment.getProperty("sex");if (sex.equals("1")) {human = new Man();} else {human = new Woman();}}@Overridepublic Human getObject() throws Exception {return human;}@Overridepublic Class<?> getObjectType() {return Human.class;}@Overridepublic boolean isSingleton() {return true;}@Overridepublic void destroy() throws Exception {System.out.println("MyFactoryBean (DisposableBean) destroy");}}

在使用中根据beanFactory的beanName来获取对象,取到的是getObject的对象。和根据bean类获取到的对象相同
在这里插入图片描述
在这里插入图片描述
如果需要获取原始Factorybean对象,需要在Factorybean前加&
在这里插入图片描述

源码分析

preInstantiateSingletons - getBean

preInstantiateSingletons方法,判断bean为FactoryBean
在这里插入图片描述

getBean

过程与前面非FactoryBean大致相同,直接来到docreateBean

doCreateBean

这里会从factoryBeanInstanceCache中获取beanName的BeanWrapper。
这个缓存是在registerBeanPostProcessors(beanFactory)的过程中就实例化了FactoryBean对象并添加到缓存中,源码略

在这里插入图片描述
BeanWrapper不为null,就不会在这进行实例化,后面的逻辑也和普通bean相同,依赖注入、调用初始化方法
在这里插入图片描述

preInstantiateSingletons - isEagerInit

获取到FactoryBean的实例在这里插入图片描述
如果FactoryBean实现了SmartFactoryBean且isEagerInit为true,会在这里更早进行初始化代理对象。
注意这里的beanName前面没有加&
在这里插入图片描述

getObjectForBeanInstance

先判断是否name以&开头,如果以&开头,表示是FactoryBean的本体name
在这里插入图片描述
在这里插入图片描述
那么直接返回本体对象
在这里插入图片描述

如果不是以&开头,从IOC容器获取到了FactoryBean的实例,调用getObjectFromFactoryBean方法来获取代理对象

getObjectFromFactoryBean

在这里插入图片描述

doGetObjectFromFactoryBean

这里调用FactoryBean的getObject方法,用来返回自定义代理实例
在这里插入图片描述
在这里插入图片描述
将代理对象放入factoryBeanObjectCache。下次再执行getBean会直接从factoryBeanObjectCache中返回对象。

AOP

自定义AOP配置

拦截以R作为返回值且类上包含@Controller、@RestController
在这里插入图片描述
被代理对象
在这里插入图片描述

源码分析

AnnotationAwareAspectJAutoProxyCreator的postProcessAfterInitialization
initializeBean时,BeanPostProcessor的postProcessAfterInitialization回调。由AnnotationAwareAspectJAutoProxyCreator类执行
先从二级缓存中获取bean,如果存在bean直接返回(已经做了代理,这段逻辑在下面加载时机二进行说明)
在这里插入图片描述

wrapIfNecessary

Wrap the given bean if necessary, i.e. if it is eligible for being proxied.
如果满足被代理条件,创建对象代理

在这里插入图片描述

shouldSkip

在这里插入图片描述

findCandidateAdvisors => findAdvisorBeans
  1. 获取继承Advisor接口的类,这里返回BeanFactoryTransactionAttributeSourceAdvisor
    在这里插入图片描述
  2. 获取包含@Aspect的类
    在这里插入图片描述在这里插入图片描述

在这里插入图片描述
下图返回我们自定义的AOP配置
在这里插入图片描述

getAdvicesAndAdvisorsForBean

Create proxy if we have advice.
如果bean有advice则创建代理

在这里插入图片描述

findEligibleAdvisors

当前bean符合被代理条件
在这里插入图片描述

作为结果返回
在这里插入图片描述

createProxy

在这里插入图片描述

proxyFactory.getProxy

在这里插入图片描述

createAopProxy
  1. 这里采用工厂设计模式,先获取AOP工厂,默认为DefaultAopProxyFactory
    在这里插入图片描述
  2. 创建AOP代理
    在这里插入图片描述
    如果当前是接口、或者实现了Proxy类、或者是Lambda类,返回JdkDynamicAopProxy
    否则返回ObjenesisCglibAopProxy
实现接口一定是使用JDK动态代理吗?不是

这里我的类是TestImportController,并且实现了BaseTestImportController接口,按理来说应该通过jdk的动态代理,但是跟源码的时候发现使用的是cglib代理,我问了chatgpt,原因是出在我的Aspect类,以下是回答
在这里插入图片描述
我根据上面的回答,又创建了一个Aspect
在这里插入图片描述
controller使用注解
在这里插入图片描述

但是在创建代理的时候依然是走的cglib
在这里插入图片描述
我又问了chatgpt
在这里插入图片描述
但是我设置了@EnableAspectJAutoProxy(proxyTargetClass = false)还是不行
看来只能手动设置Proxy来支持jdk动态代理
在这里插入图片描述在这里插入图片描述

getProxy

上面通过工厂返回了对应的AopProxy实现,接下来就是根据不同的方式创建代理对象
在这里插入图片描述
这里以cglib举例,下面是生成的代理对象
在这里插入图片描述
在这里插入图片描述

加载时机一:initializeBean时候,判断bean是否需要被代理

上述的源码分析,initializeBean的时候

加载时机二:循环依赖时提前创建代理

流程

前提:CicA和CicB为循环依赖,且两个类都会被代理

  1. CicA创建实例
  2. CicA执行populateBean来注入属性,发现有cicB
  3. CicB创建实例
  4. CicB执行populateBean来注入属性,发现有cicA
  5. CicB通过三级缓存获取到实例化的cicA,然后对cicA提前代理创建
  6. 返回代理的cicA对象,通过Field赋值属性完成CicB属性注入
  7. CicB执行initializeBean完成自身代理对象创建

源码

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
进入wrapIfNecessary方法,与普通代理逻辑一样,返回代理对象。
将代理对象加入到二级缓存
在这里插入图片描述

为什么循环需要提前创建代理

如果不提前创建代理,这时候依赖的类为普通bean,当该bean进行initializeBean创建代理之后,会出现依赖类与代理类不一致的情况,所以需要二级缓存来提前创建代理

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

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

相关文章

AI工程化实践-如何构造一个AI应用

最近大模型非常火爆&#xff0c;基于大模型的应用也层出不穷&#xff0c;比较火的比如AutoGPT&#xff0c;当然也有很多垂直领域的应用。那么如何基于大模型的能力快速的建设一个垂直领域的AI应用呢&#xff0c;这就涉及到了AI工程化建设。在整个AI工程化建设的过程中&#xff…

vue3的响应式赋值中数组array,对象object,集合set的重新赋值怎么操作,问过Chatgpt的答案

vue3和ts结合开发的时候&#xff0c;总是会遇到引用数据类型的重新赋值的情况&#xff0c;但是在vue3中&#xff0c;又不能使用直接赋值的情况&#xff0c;因为会改变proxy的结构&#xff0c;导致响应式失败&#xff0c;那么该如何重新赋值响应式对象数据成为了一个技巧问题&am…

使用gpt的感受,结尾附注册使用方式

最近一直很火的chatgpt&#xff0c;我也去试了一下&#xff0c;感觉还是用的很舒服的。 优点 感觉舒服的地方就是可以联系上下文&#xff0c;不像传统的搜索引擎一样&#xff0c;找不到的话得重新组织语言去搜索&#xff0c;可以跟gpt学习英语&#xff0c;问编程问题&#xf…

GIT使用的问题及解决

随时遇见&#xff0c;随机解决&#xff0c;同步记录 ~ 文章目录 ① git commit 失败&#xff1a;Author identity unknown *** Please tell me who you are.② git clone&#xff0c;git pull 提示 Permission denied&#xff0c;找不到私钥文件③ 重启电脑后&#xff0c;使用 …

解决Microsoft Bing 支持 ChatGPT后加入等待队列出错问题

解决Microsoft Bing 支持 ChatGPT后加入候补名单出错问题 代理进入https://www.bing.com/new&#xff0c;正确界面如下图&#xff1a; 如果进入直接跳转下图界面&#xff0c;则需要清除与bing相关的cookie&#xff08;设置里清除&#xff0c;这样就能之间跳转到加入候补名单的…

反射和动态代理

目录 v20230514更新 Userjava反射本质 反射的核心 获取Class对象&#xff1a; 创建对象&#xff1a; 调用方法&#xff1a; 访问字段&#xff1a; 需要注意的是&#xff0c; 综上所述&#xff0c; Userjava动态代理本质 两个核心的类&#xff1a;Proxy和InvocationH…

ChatGPT还在2G冲浪?新模型「youChat」:我已能够解说2022世界杯

视学算法报道 编辑&#xff1a;蛋酱、小舟 youChat 能成为搜索引擎变革的先行者吗&#xff1f; ChatGPT 自推出以来就被寄予厚望&#xff0c;一些人认为它会取代搜索引擎&#xff0c;成为「改变游戏规则的人」。 真的会有这一天吗&#xff1f;至少&#xff0c;一部分业内人士已…

流浪气球?ChatGPT这样回答,我惊了

近日&#xff0c;流浪地球电影反响热烈&#xff0c;“流浪气球”事件讨论热火&#xff0c;连人工智能ChatGPT都发表了 “自己”的看法&#xff0c;到底是怎么一回事呢&#xff1f;起因是我国一只民用气球&#xff0c;因技术和天气原因不小心飘到了米国上空&#xff0c;对方当时…

chatgpt赋能python:Python收发短信:简单可靠的解决方案

Python收发短信&#xff1a;简单可靠的解决方案 如果您需要向客户发送定期提醒或通知的短信&#xff0c;则 Python 是一种简单易用的解决方案。在本文中&#xff0c;我们将介绍如何使用 Python 发送和接收短信&#xff0c;并探讨一些流行的短信 API。 什么是短信 API&#xf…

chatgpt赋能python:Python编程——创新发短信新方式

Python编程——创新发短信新方式 在现代社会&#xff0c;短信是一种非常实用的通讯方式&#xff0c;广泛应用于各种场合。在Python编程领域中&#xff0c;通过利用各种API&#xff0c;我们能够创新地发短信并满足不同场景使用需求。本篇文章将介绍在Python编程中实现发短信的基…

chatgpt赋能python:Python短信发送:简单快捷的商业应用方式

Python短信发送&#xff1a;简单快捷的商业应用方式 介绍 随着科技的不断发展&#xff0c;短信已经成为商业沟通的重要渠道之一。许多业务场景需要使用短信进行客户沟通&#xff0c;例如短信验证码、促销短信、物流短信等等。 Python作为一种高效的编程语言&#xff0c;在短…

chatgpt赋能python:如何利用Python拦截短信验证码

如何利用Python拦截短信验证码 短信验证是现代互联网应用程序中最普遍的安全措施之一。然而&#xff0c;有些黑客试图入侵用户账户&#xff0c;通过拦截其短信验证码来获得访问权限。这可能会导致灾难性的后果&#xff0c;包括数据泄露和财务损失。 幸运的是&#xff0c;Pyth…

chatgpt赋能python:Python免费发短信:如何使用Python发送免费短信

Python免费发短信&#xff1a;如何使用Python发送免费短信 在现代社会中&#xff0c;短信已经成为人们生活中必不可少的一部分。大量的人们都使用短信来进行交流&#xff0c;包括商业交流和个人交流。如今&#xff0c;许多公司提供的短信服务费用比较高&#xff0c;这让许多用…

chatgpt赋能python:Python短信接口:如何实现高效、便捷的短信发送?

Python短信接口&#xff1a;如何实现高效、便捷的短信发送&#xff1f; 作为一项必不可少的应用&#xff0c;短信服务已成为商家与客户互动的重要手段。为此&#xff0c;短信接口成为实现短信服务的关键要素。Python作为一种优秀的编程语言&#xff0c;不仅具备高效、快速的处…

chatgpt赋能python:Python实现给手机发短信指南

Python实现给手机发短信指南 随着智能手机的普及&#xff0c;人们越来越习惯于通过短信和社交媒体来进行沟通。因此&#xff0c;发送短信已经成为了现代通讯的一部分。Python作为一种非常简单易用的编程语言&#xff0c;也可以用来发送短信。本篇文章将介绍如何使用Python在移…

chatgpt赋能python:如何使用Python发送短信

如何使用Python发送短信 短信是一种简单有效的沟通方式&#xff0c;特别是在紧急情况下。而Python作为一种著名的编程语言&#xff0c;提供了许多库来实现短信发送。在本文中&#xff0c;我们将介绍一些可用的Python库和如何使用它们发送短信。 Twilio Twilio是一个使用Pyth…

我用ChatGPT搞懂GPT技术原理,只问了30个问题,这是极致的学习体验!

自己前段时间写了一篇文章《问了ChatGPT 上百个问题后&#xff0c;我断定ChatGPT可以重塑学习范式&#xff01;》&#xff0c;讲了使用ChatGPT的感受&#xff0c;最近我开始学习GPT的技术原理&#xff0c;原因有三个&#xff1a; 1、工作中有可能要用到GPT&#xff0c;理解GPT的…

ChatGPT的插件能用了,每月 20 美元的实习生真香

文章目录 开启插件并使用其他补充缺点和不足总结 哈喽嗨&#xff01;你好&#xff0c;我是小雨青年&#xff0c;一名 追赶 AI 步伐的程序员。 自从上周 OpenAI 官宣了即将开放插件给 Plus 用户以来&#xff0c;这三天我就每天都会刷新ChatGPT 设置页面。 直到今天早上&#x…

4.AI人工智能大模型汇总:类GPT系列模型、模型中转站Auto-GPT、多模态大模型、视觉模型、自然语言模型

AI人工智能大模型汇总:类GPT系列模型、模型中转站Auto-GPT、多模态大模型、视觉模型、自然语言模型 模型名称发布方类型开源类型原始模型框架paddle版本模型能力模型语言模型参数简介模型链接体验链接paddle版本链接项目链接备注发布日期创建人模型星火认知大模型科大讯飞语言…

用GPT-4写代码不用翻墙了?Cursor告诉你:可以~~

目录 一、介绍 二、使用方法 三、其他实例 1.正则表达式 2.自动化测试脚本 3.聊聊技术 一、介绍 Cursor主要功能是根据用户的描述写代码或者进行对话&#xff0c;对话的范围仅限技术方面。优点是不用翻墙、不需要账号。Cursor基于GPT模型&#xff0c;具体什么版本不祥&#…