SpringBoot自动装配串讲

目录

  • 前言
  • 一. 基础概念
      • 1-1. Spring
      • 1-2. SpringBoot
  • 二. 自动装配概览
      • 2-1. 效果(目的)
      • 2-2. 猜想
      • 2-3. SpringBoot的实现方案
      • 2-4. 对比及分析
        • 2-4-1. starter里为什么没有pom文件
        • 2-4-2. 配置类为什么没写在starter里
  • 三. 自动装配细节
      • 3-1. 流程图
      • 3-2. 各部分细节
        • 3-2-1. @Import注入AutoConfigurationImportSelector
        • 3-2-2. AutoConfigurationImportSelector
        • 3-2-3. Spring容器启动并调用selectImports
        • 3-3. AutoConfiguration
  • 四. invokeBeanFactoryPostProcessors
      • 4-1. 先拆解一下invokeBeanFactoryPostProcessors的大体结构
      • 4-2. 实际详细过程
        • 看源码可能产生的疑问
  • 五. 特殊组件:Tomcat
      • 5-1. 创建
      • 5-2 启动
      • 5-3. 关闭
        • addShutdownHook
      • 5-4. 单独Tomcat和SpringBoot的区别
      • 5-5. 策略模式
        • Tomcat启动真的在Spring代码里?
  • 六. 总结
      • 6-1. SpringBoot的自动装配
      • 6-2. 一般组件自动装配过程
      • 6-3. 一些注意点
  • 参考

前言

本文假设读者已经有了Spring和SpringBoot的使用基础。全文一万多字,深入探讨了源码的设计模式、模块之间的关系以及容易混淆的细节。
通过剖析自动装配机制的前因后果,由浅入深的看看SpringBoot主要做了些什么事。【期间还发现了一个让人忽视的Maven特性】
都是干货,无关紧要以及说了也让人记不住的繁琐过程基本都被省略了。如果觉得文章太长,可以只看总结。如果觉得总结的还有点意思,再往前看。

一. 基础概念

概念很重要,但也很抽象空洞,在深入细节之后,再回过头看,会有新的理解。

1-1. Spring

  • 是什么:一个IOC(控制反转)容器框架。
  • 什么原理:通过依赖注入(DI,开发人员使用控制反转的方式),切面编程(AOP)实现了模块之间的解耦,模块的复用。让开发人员不再关心模块的创建(其实是不需要关心模块从生成到销毁的整个生命周期),而只需要专注于使用。
  • 目的:简化企业级java项目开发。

1-2. SpringBoot

  • 是什么:一个开箱即用的Spring集成框架(或者说脚手架。所谓脚手架,指一种支持快速搭建项目的的工具或框架。这里的意思就是说,除去Spring和其他集成的框架,SpringBoot就只是一个搭建项目的辅助工具。这里的开箱即用除了有“什么都不缺”,还有一层意思是“不需要写main方法,这个东西可以拿来直接跑”。Boot即“引导启动”,指的就是这层意思)。
  • 什么原理:通过自动装配约定大于配置原则实现(体现在两方面:1. 命名。2. 一些默认配置)。启动比较简单,就是加个main方法入口,实现可独立运行。
  • 目的:在Spring的基础上,进一步简化配置,开箱即用。(Spring是用配置简化开发,SpringBoot想把配置也简化掉)

二. 自动装配概览

2-1. 效果(目的)

  • 在项目pom.xml文件里添加相应的starter依赖,代码里就直接可以用各种组建(已经被注入Spring容器)。
  • 所有组件的配置信息都可以在SpringBoot的配置文件application.yml里统一管理。

2-2. 猜想

  • 引入组件jar包:Maven可以轻松实现这一步骤。只需要在starter中的pom文件中添加依赖,就可以满足组件所需要的jar包。
  • 自动注入:在starter里写一个配置类(@Configuration + @Bean),然后让Spring扫描到starter的包路径。配置类里把需要的Bean都创建出来。
  • 统一读配置:通常情况下,创建出组件对象之后,把各种配置参数set进对象就可以了(或者在new的时候就把参数传入构造器)。所以这部分代码同样写在配置类里就可以。按照Spring的配置规则,去classpath下的application.yml文件里读配置。

2-3. SpringBoot的实现方案

  • 读配置文件spring.factories。然后通过反射实例化xxxAutoConfigure(配置类),并将其注入到Spring容器。其实就是SpringBoot实现的SPI机制。
  • 其他和我们猜想的基本一致。
  • 有两点和我们猜想的不太一样:
    • 配置类以及读配置的代码都没写在starter包里(都写在了spring-boot-autoconfigure包里)。
    • starter包里没有pom文件。
  • 也就是说:starter里什么都没有(只有一个MANIFEST.MF:jar包信息文件)。
    在这里插入图片描述
    这是spring-boot-starter-data-redis包里的情况。

2-4. 对比及分析

2-4-1. starter里为什么没有pom文件

经过对比之后,其实最让人困惑的就是这个问题。

加载类、实例化对象和注入容器这些操作是由classloader和Spring来完成的,那么没有POM文件的情况下,依赖的jar包从何而来呢?
SpringBoot当然不会无论是否需要,统统将其依赖进来。我们通过实验,也可以明显发现:加入starter,重新构建,starter依赖的包就能加进来,否则就会被删掉。

经过网上查(没查到)/和人交流/问chatgpt/做实验,得出一个结论:

是因为jar包外的xxx.pom文件(如spring-boot-starter-data-redis-2.2.6.RELEASE.pom),starter才能依赖的其他包。

在这里插入图片描述
chatgpt给出解释是:Maven首先看jar包内的pom.xml,如果jar包内没有,则使用和jar包同名的xxx.pom文件。【虽然不能确认是否正确,但确实可以解释现象】
在这里插入图片描述

所以我总结xxx.pom文件的作用:

  1. 在使用IDEA时,当我们点击依赖包的名称时,IDEA会显示该依赖包对应的pom文件,这个pom文件就是xxx.pom文件。如果把这个文件删除,那么IDEA就无法找到该文件,从而无法显示依赖包的信息【之前一直以为idea打开的是jar包里pom.xml】
    在这里插入图片描述

  2. 当jar包内没有pom.xml时,maven以它为依据获取依赖【本次学到的】

猜想:由于存在外部的xxx.pom文件,因此并不需要使用jar包中的pom.xml文件。这样做可以省去解压jar包的步骤,从而使下载更加快速和方便。
那么,Maven是否使用的正是xxx.pom文件,而不是pom.xml文件?
由于缺乏官方的证据和参考资料,我对之前ChatGPT所提供的回答表示怀疑。【如果您能够提供官方的参考资料,请留言分享】

2-4-2. 配置类为什么没写在starter里

为了拓展性。

是的,如果所有组件都是SpringBoot管理,这个设计确实没问题。Spring扫描包的时候,注解@ComponentScan(basePackages = {"com.*"})只要覆盖到starter包里的配置类即可。

但是,Spring的很多“好东西”都会考虑可扩展:我能用,用户也要可以用。
如果用户也想使用这套机制,要引入的组件包路径就不是Spring的包路径了,Spring就可能扫描不到。
所以提供一个配置文件,在其中指定自己配置类路径,这样做能最大程度提高灵活性,让用户也可以轻松使用并扩展自己的组件。

看一下spring的这个配置文件长什么样:

在这里插入图片描述

文件采用key-value形式存储。
只在一部分jar包里有这个文件,如spring-boot, spring-boot-autoconfigure等包内。
读的时候会把classpath下所有存在的spring.factories统统读进来。

其中自动装配需要的就是key为org.springframework.boot.autoconfigure.EnableAutoConfiguration
注意右侧的value值,该值通常很长,并用逗号隔开,而且名字一个个都叫“xxxAutoConfiguration”,表示这都是配置类(带注解@Configuration的)。

那文件里其他的key呢?
SpringBoot启动过程中还有很多流程,也会用到这个文件。比如各种Listener。也都是读配置,然后反射加载然后实例化的。

三. 自动装配细节

3-1. 流程图

在这里插入图片描述

3-2. 各部分细节

3-2-1. @Import注入AutoConfigurationImportSelector

找到SpringBoot的启动类Application上的注解@SpringBootApplication,点进去。
找到@EnableAutoConfiguration,点进去。
最后就可以看到注解@Import(AutoConfigurationImportSelector.class)

在这里插入图片描述

注解和普通类一样具有继承特性,所以相当于Application也使用了注解@Import,并注入了AutoConfigurationImportSelector。

3-2-2. AutoConfigurationImportSelector

AutoConfigurationImportSelector不是一个普通类,它继承了DeferredImportSelector

实现了其中的方法selectImports

在这里插入图片描述
可以看到selectImports返回了一个String[],其实返回的就是上图中的A(配置文件spring.factories)里的内容。

那么,这个selectImports方法是被谁调用的呢?就是上图中所示[3]的位置。简单来说,在SpringBoot启动过程中被调用,但这个过程非常复杂。因此,我们需要逐层剖析SpringBoot和Spring的启动过程,直到找到调用该方法的位置。

3-2-3. Spring容器启动并调用selectImports

这部分,我们从一个大家都熟悉的地方开始讲起,比较容易让读者理解。

这里之所以还要讲Spring的启动流程,是因为讲SpringBoot的启动流程,绕不开Spring的启动流程。从某种程度上说,SpringBoot并没有什么独创性的功能,即便是核心的自动装配,也是依赖Spring才得以实现的。

SpringBoot这种非常不独立,以及存在感弱的特点。也就导致很多人用了许久,也说不清楚SpringBoot到底是个什么东西。
比起Spring,它似乎就是多了一个main方法,配置比较方便而已(事实上,这确实就是SpringBoo的全部功能)。

但功能简单并不代表意义平凡。Spring说起来,实现机制那么复杂,但目的无非也是简化开发。

两个核心方法:

  • Spring启动核心方法:org.springframework.context.support.AbstractApplicationContext类里的refresh()。

    AbstractApplicationContext也是Spring的核心类之一,属于spring-context包。

    启动Spring容器的时候,无论是用xml还是注解,都会走到refresh()方法。

  • SpringBoot启动核心方法:org.springframework.boot.SpringApplication类里的run(String… args)。

    SpringApplication是SpringBoot核心类,属于spring-boot包。

    启动springBoot时,执行SpringApplication.run(Application.class, args),很快就会进入run方法。

先直观的看一下着两个核心方法,左边的是SpringBoot的,右边是Spring的

请添加图片描述
注意看黄色箭头标注的位置,就是SpringBoot通向Spring核心启动方法的位置。

SpringBoot属于spring的子项目。如果按照java对象的父子关系,子类包含父类来类比。
放在这里,就是SpringBoot内包含了spring。 启动过程也是这样的包含关系。

后面再说源码的时候,我都会以这两块代码为“坐标”来说,这样就不至于出现“搞不清身在何处”的问题了。

右边箭头标注的invokeBeanFactoryPostProcessors(beanFactory);就是处理selectImports方法的入口。

所以:spring.factories里的AutoConfiguration配置类是Spring容器启动过程中的PostProcessor注入的

如果要继续深入下去,找具体的调用点,请看后面第四节[invokeBeanFactoryPostProcessors]。
因为PostProcessor代码很复杂,我单独分出一块来讲。这里不再赘述。

3-3. AutoConfiguration

SpringBoot费那么大的劲,通过SPI机制,实例化出来个什么东西呢。
以spring-boot-starter-data-redis(用redis时需要加的starter)为例

在这里插入图片描述

这是在spring.factories里,"RedisAutoConfiguration"是value里一员。

为什么默认就在配置里了,我还没想用redis呢。
因为要让一个starter真正用起来,spring.factories的配置和pom.xml里的依赖缺一不可(SpringBoot就等着你在pom.xml里加redis的starter呢)。

请添加图片描述

当这个配置类被实例化并注入Spring容器之后。其中配置的两个Bean(Redis组件):RedisTemplate<Object, Object> 和StringRedisTemplate也就被自动注入到了Spring容器。

其中注解@EnableConfigurationProperties是用来将properties或yml配置文件属性转化为Bean对象。括号里的属性写要封装的Bean类型。打开这个类
请添加图片描述

通过这个@ConfigurationProperties(prefix = "spring.redis")注解,就可以自动从配置文件中读配置并封装到当前对象中。redis的配置规则就是以spring.redis开头。

注意:什么叫配置类?前面展示两个类,哪个是配置类?

在Spring中,前者(注入Bean的)叫配置类。就是使用@Configuration或者@Component、@ComponentScan、@Import、@ImportResource等叫配置类(一般我们习惯只把@Configuration叫配置类)。

而@ConfigurationProperties的类是用来封装配置信息的,却不叫配置类。

四. invokeBeanFactoryPostProcessors

这部分主要是讲Spring的重要组成部分:Bean后置处理器PostProcessor的源码。

4-1. 先拆解一下invokeBeanFactoryPostProcessors的大体结构

在这里插入图片描述

这张图只是抽象出了一个非常简单的过程(实际过程比这复杂的多):

在PostProcessorRegistrationDelegate这个类中

  1. 先遍历调用接口BeanDefinitionRegistryPostProcessor的方法。其中本次关注的主角selectImports就是在这部分里完成的。
  2. 然后遍历调用BeanFactoryPostProcessor的方法(用户大部分的扩展都是通过继承这个接口,在这个过程中执行的)

看一下这两个接口的注释:

先看第二个接口的,BeanFactoryPostProcessor
请添加图片描述
注意看标注的位置,核心就是说这个单词:hook
很常规的扩展手段,通过钩子方法来让用户来插入自己自定义内容。也是PostProcessor功能的核心。

然后看BeanDefinitionRegistryPostProcessor
请添加图片描述
首先,它继承了前面那个BeanFactoryPostProcessor。
关键单词:SPI。就是说这是SpringBoot实现的SPI机制。通过一个配置文件(spring.factories)来加载其他类。
意思就是说:这个接口也是一个处理Bean的钩子(因为继承了那个钩子),只不过功能相对更加单一。具有通过SPI机制,读配置批量加注入Bean的功能。

4-2. 实际详细过程

在这里插入图片描述

过程相对复杂。尤其是最终解析配置类的类ConfigurationClassParser(上图下半部分)。递归调用(为了一层层往下找注解),代码绕来绕去的。【这个图仅供看源码时参考,这也仅仅是一部分关键的节点】

看源码可能产生的疑问

  • selectImports被调用的地方藏的那么深,你是怎么找到的?
    对我来说,首先是查资料,知道了关键代码selectImports。然后就是就是搜代码,找selectImports被谁调用的(理解了后面两个问题之后才会知道为什么在哪个位置)。
  • selectImports为什么在“处理配置类”的代码里?
    前面我们说“什么叫配置类”。配置类其实包含的内容很广,不仅仅是@Configuration的。@Import也属于配置类的范畴(具体看这篇博客)。
  • selector是什么意思?
    Spring的“约定大于配置”,其中一个就是命名上的约定。Spring会有很多“常见的名词”,如Ware,Configure。而Selector表示一种“选择器”,是一种选择或筛选机制。这里就是选择Bean的机制(配置文件里写上全类名)。

五. 特殊组件:Tomcat

其实就是说的Web容器。对于普通组件,就是new一下,set一些参数就能用了。但Web容器还多了一步:启动。而且要包含在SpringBoot的启动过程中。

我们猜想,Tomcat的创建和启动应该是在SpringBoot代码里,毕竟Tomcat太特殊了。
但实际上Tomcat的创建和启动都是在Spring容器创建过程中。

5-1. 创建

在Spring启动的核心方法里,进入onRefresh()里,就能找到创建Tomcat对象的位置。
在这里插入图片描述

5-2 启动

很多人认为,前面代码执行完之后就算Tomcat启动了(相关日志也打印出来了),但实际并没有。前面只是创建了Tomcat实例并初始化。

启动代码在这里面
在这里插入图片描述
是不是很意外,Tomcat的创建启动不但放在Spring里,而且还拆的那么散。

5-3. 关闭

还有更意外的。Tomcat启动了,我们还有考虑关闭的问题。SpringBoot关闭之后,还要考虑连带着把Tomcat一并关掉。

这个就涉及到JVM关闭前的钩子函数。位置在启动Spring容器之后

在这里插入图片描述

addShutdownHook

Runtime.getRuntime().addShutdownHook(进程);
作用:在jvm关闭前,执行这个线程。
问题:强制杀进程,这个进程也会被执行吗?
实验结果:不会。强制执行,这个进程不会被执行。
实验方式

  1. 对照组:启动SpringBoot,然后正常关闭(idea里点关闭按钮),看日志。
  2. 实验组:启动SpringBoot,然后找到进程,强制kill掉,看日志。

实验结果
正常关闭的有这样的日志:
2023-03-13 12:28:06.440 [SpringContextShutdownHook] INFO o.s.scheduling.concurrent.ThreadPoolTaskExecutor-Shutting down ExecutorService 'applicationTaskExecutor'
而强制kill的没有(自己写demo也能验证)。

思考:那所谓正常关闭,是怎么关的?
其实就和SpringBoot的启动方法run一样,都在SpringApplication类里,叫exit

在这里插入图片描述

5-4. 单独Tomcat和SpringBoot的区别

  • 单独启动Tomcat。Tomcat是一个单独的jvm进程。
  • SpringBoot里的Tomcat成为了SpringBoot程序的一部分。像new普通组件一样,new出来的,只不过多了一步start。
    可以类比为 你的项目需要对外开放一个webservice接口。那么此时,你的项目就多占用了一个端口。
    但整个SpringBoot项目还是一个完整的jvm进程。
    使用ps -ef | grep java可以看一下,只有SpringBoot进程,并没有多出来一个Tomcat进程。

5-5. 策略模式

思考:Tomcat那么特殊的组件放在Spring里真的合适吗?不会把Spring正常的流程搞的一团糟吗?

现象:有些人可能找不到启动Tomcat的代码在哪里。因为在refresh方法里的finishRefresh(),点进去,发现并不是我上面截图的那个方法。

以上两件事共同引出了:Spring启动过程采用了策略模式

先说找不到方法的问题。那个方法其实在ServletWebServerApplicationContext类中。如果你是debug,就会自然点进这个方法里。否则就会点进AbstractApplicationContext自己的finishRefresh()。看下面这个继承关系

在这里插入图片描述

也就是说,父类调用了子类的重写的finishRefresh()方法(这个说法其实不准确。如果你对这种现象比较困惑,请看我的另一篇博客复杂父子继承相互调用的深入理解)

再回头看一下SpringBoot的启动核心代码

在这里插入图片描述

在这里,也就是把context传入Spring启动流程之前。context的真实类型就已经是子类ServletWebServerApplicationContext。所以进入Spring流程,后面的很多Web相关的个性化代码都是在这个子类里执行的。

这是一个策略模式应用方式

  • 有一个公共抽象父类(抽象策略类),实现一些通用的方法。【如AbstractApplicationContext】
  • 一堆子类(具体策略类)去继承。【如ServletWebServerApplicationContext】
  • 最后把披着父类外衣的子类传到一个上下文环境类中执行【如SpringApplication】。会让父类表现出某个子类的行为特性。

这样子类的个性化行为就不会影响到公共父类的代码了。

Tomcat启动真的在Spring代码里?

前面看似“自圆其说”了,但其实并不对。
事实上,Tomcat启动的过程不但使用了策略模式,单独另外写了一个子类。而且这个子类实际上属于SpringBoot的代码。这是全类名
org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext

现在是不是就很圆满了:SpringBoot没有动Spring代码。只是在自己的包下重写了一个AbstractApplicationContext的子类。看起来就成功侵入了Spring的流程,把Tomcat启动等一众Web特殊操作给塞进去了。
这才是策略模式的正确打开方式。

六. 总结

6-1. SpringBoot的自动装配

  • StringBoot主要就是实现了一个自动装配功能。通过添加starter的方式,让用户快速使用组件。
  • 特殊的web组件,如Tomcat。是通过策略模式的方式嵌入在Spring容器启动的过程中。
    一般组件如redis。是通过配置类的方式注入。配置类相关代码写在spring-boot-autoconfigure包里。配置类本身又是通过SPI的机制来加载的。用户也可以用这套机制添加自己的扩展。

6-2. 一般组件自动装配过程

  1. SpringBoot通过@Import标签,注入AutoConfigurationImportSelector对象。
  2. AutoConfigurationImportSelector类中有个ImportSelector方法,读取spring.factories配置文件。
  3. 在Spring启动过程中,PostProcessor阶段调用了其中的ImportSelector接口方法,通过反射实例化了配置文件中的配置类。
  4. 配置类创建并注入了starter需要的组件Bean。
  5. 创建Bean的过程中,统一去SpringBoot的配置中读取组件自己的配置。

6-3. 一些注意点

  • SpringBoot对Spring使用了策略模式。所以SpringBoot并不是简单嵌套了一下Spring。它是确实对Spring动了一些手脚,只不过是无侵入的。
  • 别把SpringBoot中的Tomcat当作独立的进程。在SpringBoot里,Tomcat也是一个组件。所有组件都相当于SpringBoot代码的一部分。所以我前文写到“SpringBoot关闭之后,还要考虑连带着把Tomcat一并关掉 ”,其实是不对的。SpringBoot和Tomcat是同一个进程,这里所说的关闭,其实是他们各自的一些资源,比如连接什么。
  • 由上面两点,我们再回忆一下没有SpringBoot的时代,看看发生了什么:
    • 过去:本质上,JavaWeb其实是在“完善Tomcat程序”(包括Spring在内的,我们写所有程序都是Tomcat的一部分)。
    • 现在:本质上,包括Tomcat在内的所有组件,以及我们写的代码,都是SpringBoot的一部分。
    • 所以:SpringBoot真的不像我们感觉的那么简单。Spring做到了Java行业事实上的标准。而SpringBoot在开发形式上逆转上位,做到了霸主地位(内在强大了,外在的地位也要跟上嘛)。
  • starter包里什么都没有,甚至没有pom文件。用的是Maven仓库中和starter同名的xxx.pom文件做的依赖【也是本文遗留的不太确定的解释】。
  • Runtime.getRuntime().addShutdownHook()在使用强制杀进程(kill -9 pid)时不会被调用。具体看这篇博客。

参考

SpringBoot自动装配原理分析二
spring注解之@Import注解的三种使用方式
Spring 使用 @Import 的好处
spring解析配置类
Runtime.getRuntime().addShutdownHook()

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

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

相关文章

告别抠图!海量免抠PNG,任你选

无论处理图片还是做PPT&#xff0c;经常会用到透明背景的图片素材&#xff0c;往往这种时候就需要进行抠图加 工。对PS图技术不佳的小伙伴而言&#xff0c;要抠出一张完美的图片并非易事。但也不是难事&#xff0c;只要你 有免抠PNG素材网&#xff08;搜图114 www.sotu114.co…

自己用ps抠图标

大家进入项目阶段已经有差不多一个月了&#xff1b;从简单数据库分析到慢慢的调试页面&#xff1b;再到 灵活的进行增删查改&#xff1b;相信在这一个月里大家的代码技术都有了一定的提高&#xff1b;相信对于以前学的现在是更加熟练了。对于不会的&#xff0c;可以通过网上查找…

不会PS怎么抠图换背景?赶紧收藏这3个好用的一键抠图神器

在现代社交媒体的世界里&#xff0c;给一张图片抠图换背景已经成为了互联网上很普遍的需求&#xff0c;比如有些朋友可能需要在社交媒体上分享自己的照片或制作一些创意性的设计作品&#xff0c;抠图换背景就可以帮助把图片创造出更好的视觉效果。一提到抠图去除背景&#xff0…

抠图软件哪个好用?这些软件你了解吗?

我们在抠取图片中的元素时&#xff0c;偶尔需要将图片中的人物抠出来。比如通过抠人像的方式&#xff0c;给证件照更换背景&#xff1b;或者制作搞怪照片&#xff0c;玩法多样。不过我们需要选择一款适合自己的人像抠图软件&#xff0c;所以人像抠图软件哪个好&#xff1f;快往…

GIMP:利用蒙板工具实现人像抠图

GIMP&#xff1a;利用蒙板工具实现人像抠图 利用蒙板工具进行抠图简单介绍方法步骤1.打开图像2.复制图层3.选中图层4.将图层改为单色5.人像与背景分离6.反相显示7.人像部分描白8.添加图层蒙板9.粘贴白色人像轮廓10.图层不可视11.解决人像范围不正确12.随意更换图像背景 利用蒙板…

抠图软件哪个好用又免费?快来看看这几款软件

相信大家都使用过社交软件吧&#xff0c;有时候我们在里面看到的那些精美的图片、有趣的视频&#xff0c;大部分都是经过软件处理出来的。而当我们要在社交软件上分享自己的日常时&#xff0c;也会自带修图、滤镜、抠图等功能&#xff0c;但是用起来有时会难以达到自己想要的那…

PHP Imagick 去背景 (抠图专用)

最近接到一个项目需要用到电子签章。 需求&#xff1a;章、人员签名&#xff0c;盖在白纸或手写在白纸上通过拍照的方式上传到系统。 前期是公司小妹通过PS把图片扣出来&#xff0c;弄成透明的背景然后上传。 这样每次有新增都需要人工处理&#xff0c;不方便和智能&#xff0c…

开发了一个抠图/去背景应用

jr们早上好 iPhone 的 iOS 16有个很酷的功能&#xff0c;长按照片就能把其中的拍摄主体提取出来&#xff0c;抠图过程比一般的抠图App方便&#xff0c;精细度也更高。 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KIlpLyow-1680141413142)(https…

抠图应用程序设计(三)——QT用户界面的实现

简介 ​ 本设计的GUI其实是由一个用户界面demo开发而成&#xff0c;主要由弹窗以及主界面组成。弹窗主要用于提示用户操作&#xff0c;为用户提供选择&#xff1b;主界面用于交互功能的实现。 外观设计 ​ 外观设计部分大部分在Qt Designer上完成。将所需控件按照方案论证中…

【虚幻引擎UE】UE5 AR初体验之静态动态模型加载

UE5的AR初体验之静态动态两种模型加载 基于配置好AR环境&#xff08;参考另一篇文章&#xff09; 先## 标题简单了解一下它的项目结构 这里的brush就是我们的操作空间范围 官方模板可以实现平面识别&#xff0c;控制对象的旋转和缩放。 本文主要说明在AR项目中实现模型加载…

在虚幻引擎5中构建你的首款游戏 - 04 - 地形和草地

在虚幻引擎5中构建你的首款游戏 - 04 - 地形和草地 前言介绍: 原版地址: << [功能亮点]在虚幻引擎5中构建你的首款游戏(官方字幕)_哔哩哔哩_bilibili >> << https://www.bilibili.com/video/BV1M34y1x7tc >> 官网地址: << Your First Game In Un…

虚幻引擎(UE5)-大世界分区WorldPartition教程(三)

文章目录 前言LevelInstance的使用1.ALevelInstance2.选择Actor创建关卡3.运行时加载LevelInstance 总结 上一篇&#xff1a;虚幻引擎(UE5)-大世界分区WorldPartition教程(二) 前言 在制作大关卡时&#xff0c;可能会遇到这样一种情况&#xff0c;就是关卡中的某些Actor会重复…

虚幻引擎5 学习笔记2

一、visual studio 2019添加工作负荷 选中工具-获取工具和功能 点击工作负载-勾选要添加的负载——“使用c的桌面开发”和“使用c的游戏开发” “” 二、创建项目 创建一个c的项目&#xff0c;初学者包也勾上。名字不要有中文。 报错&#xff1a; 提示缺少了net程序&…

在虚幻引擎5中构建你的首款游戏 - 05 - 岩石和植物

在虚幻引擎5中构建你的首款游戏 - 05 - 岩石和植物 前言介绍: 原版地址: << [功能亮点]在虚幻引擎5中构建你的首款游戏(官方字幕)_哔哩哔哩_bilibili >> << https://www.bilibili.com/video/BV1M34y1x7tc >> 官网地址: << Your First Game In Un…

虚幻引擎(UE5)-大世界分区WorldPartition教程(四)

文章目录 前言一、Data Layers的使用1.添加Actor到Data Layers2.运行时处理 总结 上一篇&#xff1a;虚幻引擎(UE5)-大世界分区WorldPartition教程(三) 前言 Data Layers&#xff08;UE4中叫Layers&#xff09;用于将Actor划分到不同的Layer中&#xff0c;通过在编辑器和运行…

UE5使用MetaHuman构建超现实的角色

使用免费的MetaHuman创造者应用程序为虚幻构建超现实的角色。 流派:电子学习| MP4 |视频:h264&#xff0c;1280720 |音频:AAC&#xff0c;48.0 KHz 语言&#xff1a;英语中英文字幕&#xff08;根据原英文字幕机译更准确&#xff09;|大小解压后:1.66 GB 含课程文件|时长:1h 49…

虚幻引擎5改变了游戏,并与Perforce原生集成

游戏发展|版本控制 作者&#xff1a;Ryan L Italien 虚幻引擎是当下流行的游戏引擎之一。虽然很多团队喜欢UE4&#xff0c;但虚幻引擎5 (UE5)的抢先版本包含了一些期待已久的改进(加上一些令人惊叹的新功能)。 这篇文章将分析我们为什么对虚幻引擎 5 感到如此兴奋。此外&…

UE5 最新动态虚幻引擎全新版本引爆互联网

自 1998 年上市以来&#xff0c;虚幻引擎一直是顶级游戏开发工具之一。一些史上最大型游戏 —《杀出重围》和《生化奇兵》系列、《火箭联盟》、《堡垒之夜》等等 — 均使用该引擎的不同迭代版本进行构建。 随着电影和电视行业日益认识到虚拟引擎的作用&#xff0c;甚至在游戏业…

UE4 回合游戏项目 22- 控制新角色

在上一节&#xff08;UE4 回合游戏项目 21- 添加多种类型的敌人&#xff09;基础上新添加一个玩家角色 效果&#xff1a; 步骤&#xff1a; 1.打开进阶游戏资源&#xff0c;解压“回合迁移_第七节&#xff08;只是新人物包&#xff09;” 2.解压后双击打开工程 3.选中“ziyuan…

腾讯发布 3D 虚拟场景自动生成解决方案,用 AIGC 助力游戏开发提效

3月28日记者获悉&#xff0c;腾讯 AI Lab在2023游戏开发者大会&#xff08;Game Developers Conference&#xff09;上发布了自研的3D游戏场景自动生成解决方案&#xff0c;通过AIGC技术&#xff0c;帮助开发者在极短的时间内打造出高拟真、多样化的虚拟城市场景&#xff0c;大…