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

系列十六、Spring IOC容器的扩展点

一、概述

        Spring IOC容器的扩展点是指在IOC加载的过程中,如何对即将要创建的bean进行扩展。

二、扩展点

2.1、BeanDefinitionRegistryPostProcessor

2.1.1、概述

        BeanDefinitionRegistryPostProcessor是bean定义的后置处理器,在BeanDefinition加载后,实例化bean之前,调用 invokeBeanFactoryPostProcessors时进行扩展,通过改变BeanDefinition的定义信息进行扩展,源码如下:

2.1.2、继承结构

2.1.3、案例

2.1.3.1、ATM
/*** @Author : 一叶浮萍归大海* @Date: 2023/11/23 15:06* @Description:*/
@Slf4j
@Component(value = "atm")
public class ATM {public int withdrawMoney(int money) {log.info("取钱方法正在执行...");if (money == 100) {throw new RuntimeException("自定义的异常");}return money;}}
2.1.3.2、MySpringConfig
/*** @Author : 一叶浮萍归大海* @Date: 2023/11/23 15:29* @Description:*/
@Configuration
@ComponentScan(basePackages = {"org.star"})
public class MySpringConfig {}
 2.1.3.3、MyBeanDefinitionRegistryPostProcessor 
/*** @Author : 一叶浮萍归大海* @Date: 2023/11/25 17:38* @Description:*/
@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {/*** 作用:动态注册BeanDefinition* 调用时机:IOC加载时注册BeanDefinition的时候会调用* @param registry the bean definition registry used by the application context* @throws BeansException*/@Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {RootBeanDefinition definition = new RootBeanDefinition(ATM.class);// 设置ATM bean为多实例definition.setScope("prototype");registry.registerBeanDefinition("atm",definition);}@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {BeanDefinition beanDefinition = beanFactory.getBeanDefinition("atm");// 将atm设置为懒加载,这样在容器启动时将不会创建bean,只有在getBean时才会创建对象beanDefinition.setLazyInit(true);}
}
2.1.3.4、AopFullAnnotationMainApp 
/*** @Author : 一叶浮萍归大海* @Date: 2023/11/23 15:14* @Description:*/
@Slf4j
public class AopFullAnnotationMainApp {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MySpringConfig.class);ATM atm1 = context.getBean("atm", ATM.class);ATM atm2 = context.getBean("atm", ATM.class);log.info("atm1:{},atm2:{},(atm1 == atm2):{}", atm1,atm2,(atm1 == atm2));}}

 

2.2、xxxAware接口

2.2.1、概述

        Spring中存在着大量的xxxAware接口实现类,用于在bean初始化完成之前做一些前置操作,程序员可以自己实现xxxAware接口,重写里边的方法修改bean的定义信息,进行扩展。

2.2.2、继承结构

2.2.3、案例

2.2.3.1、ATM

同上。

2.2.3.2、MySpringConfig

同上。

2.2.3.3、MyApplicationContextAware
/*** @Author : 一叶浮萍归大海* @Date: 2023/11/25 18:51* @Description:*/
@Component
public class MyApplicationContextAware implements ApplicationContextAware {public ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;AnnotationConfigApplicationContext context = (AnnotationConfigApplicationContext) applicationContext;ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();BeanDefinition beanDefinition = beanFactory.getBeanDefinition("atm");beanDefinition.setScope("prototype");}}
2.2.3.4、AopFullAnnotationMainApp

同上。

2.2.3、调用链路

2.2.4、注意事项

        通过观察 2.1.3.4和 2.2.3.4的执行结果,不能发现xxxAware接口中配置的扩展覆盖了BeanDefinitionRegistryPostProcessor中的配置,说明xxxAware的优先级更高,这个也很好理解,对于同样的一个bean,后边的配置肯定会覆盖掉前边的配置。

2.3、生命周期回调时进行扩展

2.3.1、概述

        bean的生命周期回调主要分为两种,一种是初始化进行调用,另外一种是销毁时进行调用,但是不管是初始化还是销毁,都对应着三种方式,即:

        a、@PostConstruct @PreDestroy
        b、实现接口 InitializingBean, DisposableBean的方式
        c、@Bean(initMethod = "init",destroyMethod = "destroy")的方式

2.4、初始化后实例化前进行扩展

2.4.1、bean创建完成的标识

        当循环完所有的DeanDefinition后,bean就创建完了。

2.4.2、大致流程

启动IOC容器 ===> refresh() ===>finishBeanFactoryInitialization(beanFactory)===>beanFactory.preInstantiateSingletons()

2.4.3、源码解析

#1、启动IOC容器
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MySpringConfig.class);#2、refresh()
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {this();register(componentClasses);refresh();
}# 3、finishBeanFactoryInitialization(beanFactory)
@Override
public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {// Prepare this context for refreshing.prepareRefresh();// Tell the subclass to refresh the internal bean factory.ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// Prepare the bean factory for use in this context.prepareBeanFactory(beanFactory);try {// Allows post-processing of the bean factory in context subclasses.postProcessBeanFactory(beanFactory);// Invoke factory processors registered as beans in the context.invokeBeanFactoryPostProcessors(beanFactory);// Register bean processors that intercept bean creation.registerBeanPostProcessors(beanFactory);// Initialize message source for this context.initMessageSource();// Initialize event multicaster for this context.initApplicationEventMulticaster();// Initialize other special beans in specific context subclasses.onRefresh();// Check for listener beans and register them.registerListeners();// Instantiate all remaining (non-lazy-init) singletons.finishBeanFactoryInitialization(beanFactory);// Last step: publish corresponding event.finishRefresh();}catch (BeansException ex) {if (logger.isWarnEnabled()) {logger.warn("Exception encountered during context initialization - " +"cancelling refresh attempt: " + ex);}// Destroy already created singletons to avoid dangling resources.destroyBeans();// Reset 'active' flag.cancelRefresh(ex);// Propagate exception to caller.throw ex;}finally {// Reset common introspection caches in Spring's core, since we// might not ever need metadata for singleton beans anymore...resetCommonCaches();}}
}# 4、beanFactory.preInstantiateSingletons();
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {// Initialize conversion service for this context.if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {beanFactory.setConversionService(beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));}// Register a default embedded value resolver if no bean post-processor// (such as a PropertyPlaceholderConfigurer bean) registered any before:// at this point, primarily for resolution in annotation attribute values.if (!beanFactory.hasEmbeddedValueResolver()) {beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));}// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);for (String weaverAwareName : weaverAwareNames) {getBean(weaverAwareName);}// Stop using the temporary ClassLoader for type matching.beanFactory.setTempClassLoader(null);// Allow for caching all bean definition metadata, not expecting further changes.beanFactory.freezeConfiguration();// Instantiate all remaining (non-lazy-init) singletons.beanFactory.preInstantiateSingletons();
}# 5、beanFactory.preInstantiateSingletons();
@Override
public void preInstantiateSingletons() throws BeansException {if (logger.isTraceEnabled()) {logger.trace("Pre-instantiating singletons in " + this);}// Iterate over a copy to allow for init methods which in turn register new bean definitions.// While this may not be part of the regular factory bootstrap, it does otherwise work fine.List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);// Trigger initialization of all non-lazy singleton beans...for (String beanName : beanNames) {RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {if (isFactoryBean(beanName)) {Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);if (bean instanceof FactoryBean) {final FactoryBean<?> factory = (FactoryBean<?>) bean;boolean isEagerInit;if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)((SmartFactoryBean<?>) factory)::isEagerInit,getAccessControlContext());}else {isEagerInit = (factory instanceof SmartFactoryBean &&((SmartFactoryBean<?>) factory).isEagerInit());}if (isEagerInit) {getBean(beanName);}}}else {getBean(beanName);}}}// Trigger post-initialization callback for all applicable beans...for (String beanName : beanNames) {Object singletonInstance = getSingleton(beanName);if (singletonInstance instanceof SmartInitializingSingleton) {final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;if (System.getSecurityManager() != null) {AccessController.doPrivileged((PrivilegedAction<Object>) () -> {smartSingleton.afterSingletonsInstantiated();return null;}, getAccessControlContext());}else {smartSingleton.afterSingletonsInstantiated();}}}
}

2.4.4、通过监听器扩展

2.4.4.1、Computer
/*** @Author : 一叶浮萍归大海* @Date: 2023/11/27 11:52* @Description:*/
@Getter
@Setter
@Accessors(chain = true)
@Component
public class Computer {/*** 电脑名称*/private String name;/*** 品牌*/private String brand;}
2.4.4.2、 MyContextRefreshedEvent 
/*** @Author : 一叶浮萍归大海* @Date: 2023/11/27 11:48* @Description: 监听器*/
@Component
public class MyContextRefreshedEvent {@EventListener(ContextRefreshedEvent.class)public void onContextRefreshedEvent(ContextRefreshedEvent event) {System.out.println(event);// bean初始化完成后做扩展,扩展代码写在这里ConfigurableApplicationContext context = (ConfigurableApplicationContext) event.getApplicationContext();DefaultListableBeanFactory factory = (DefaultListableBeanFactory) context.getBeanFactory();BeanDefinition beanDefinition = factory.getBeanDefinition("computer");beanDefinition.setScope("prototype");factory.registerBeanDefinition("computer",beanDefinition);System.out.println("all singleton beans loaded,onContextRefreshedEvent execute success!");}}
2.4.4.3、MySpringConfig(同上)
2.4.4.4、AopFullAnnotationMainApp 
@Slf4j
public class AopFullAnnotationMainApp {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MySpringConfig.class);Computer computer1 = context.getBean(Computer.class);Computer computer2 = context.getBean(Computer.class);log.info("computer1:{},computer2:{},(computer1 == computer2 ?) : {}",computer1,computer2,(computer1 == computer2));}
}

2.4.5、通过接口扩展

2.4.5.1、Computer
/*** @Author : 一叶浮萍归大海* @Date: 2023/11/27 11:52* @Description:*/
@Getter
@Setter
@Accessors(chain = true)
@Component
@Slf4j
public class Computer {/*** 电脑名称*/private String name;/*** 品牌*/private String brand;public void init() {Computer computer = new Computer().setName("OptiPlex7010MT Plus13").setBrand("戴尔");log.info("Computer's init was invoked! computer:{}", JSON.toJSONString(computer));}}
2.4.5.2、MySmartInitializingSingleton
/*** @Author : 一叶浮萍归大海* @Date: 2023/11/27 13:04* @Description:*/
@Component
public class MySmartInitializingSingleton implements SmartInitializingSingleton {@Resourceprivate ApplicationContext applicationContext;@Overridepublic void afterSingletonsInstantiated() {ConfigurableApplicationContext context = (ConfigurableApplicationContext) applicationContext;DefaultListableBeanFactory factory = (DefaultListableBeanFactory) context.getBeanFactory();BeanDefinition beanDefinition = factory.getBeanDefinition("computer");beanDefinition.setInitMethodName("init");beanDefinition.setScope("prototype");factory.registerBeanDefinition("computer",beanDefinition);System.out.println("all singleton beans loaded,afterSingletonsInstantiated execute success!");}
}
2.4.5.3、MySpringConfig(同上)
2.4.5.4、AopFullAnnotationMainApp(同上) 

相关文章:

系列十六、Spring IOC容器的扩展点

一、概述 Spring IOC容器的扩展点是指在IOC加载的过程中&#xff0c;如何对即将要创建的bean进行扩展。 二、扩展点 2.1、BeanDefinitionRegistryPostProcessor 2.1.1、概述 BeanDefinitionRegistryPostProcessor是bean定义的后置处理器&#xff0c;在BeanDefinition加载后&a…...

eclipse项目移到idea上部署运行

1.配置web模块 另外&#xff0c;模块这里&#xff0c;也要加上Spring 2.配置Artifact &#xff08;用于tomcat&#xff09; 就是从上面配置的web模块&#xff0c;产生的工件 3.添加lib 一般是在web-inf/lib &#xff0c; 遇到的坑&#xff1a; jdk版本问题&#xff0c;这里…...

支持向量机的算法原理

支持向量机&#xff08;Support Vector Machine&#xff0c;简称SVM&#xff09;是机器学习领域中一种常用的分类算法&#xff0c;它基于统计学习理论和结构风险最小化原则&#xff0c;具有很强的理论基础和良好的分类性能。本文将详细介绍支持向量机的算法原理&#xff0c;并解…...

gitlab 12升级14(解决各种报错问题)

1.这里是从自己公司的源下载的rpm包&#xff0c;需要换成自己的 2.从12的最后一个版本升级到14的最后一个版本 # 停服务 [rootdocker test]# gitlab-ctl stop puma && gitlab-ctl stop sidekiq && gitlab-ctl stop nginx && gitlab-ctl status# 进入…...

给element plus中动态form-item增加校验的可行方法

element plus中的form组件自带校验机制。在常规使用场景中&#xff0c;表单项是固定的、明确的&#xff0c;且数量不会太多。校验规则的使用也如下&#xff1a; <template><div class"edit-page"><el-form :model"formModel" ref"for…...

C++学习之值传递

c/c中存在三种传值方式&#xff0c;在局部函数中&#xff0c;对这三种传值方式传入的参数进行修改&#xff0c;会得到不同的结果。具体见下例&#xff1a; #include <stdlib.h> #include <stdio.h>static int dummny 10000;// 传值(传过来的是原始值的副本&#…...

网络视频播放卡顿原因分析

一、问题描述 某项目通过拉摄像机rtsp流转rtmp/http-flv/ws-flv的方案&#xff0c;使用户可以在网页中观看摄像机的视频画面。在 观看视频时偶发出现卡顿现象。 二、卡顿现象分析和解决 此问题涉及的原因较多&#xff0c;所以得考虑各环节的问题可能性&#xff0c;并根据现场实…...

Android 相机库CameraView源码解析 (二) : 拍照

1. 前言 这段时间&#xff0c;在使用 natario1/CameraView 来实现带滤镜的预览、拍照、录像功能。 由于CameraView封装的比较到位&#xff0c;在项目前期&#xff0c;的确为我们节省了不少时间。 但随着项目持续深入&#xff0c;对于CameraView的使用进入深水区&#xff0c;逐…...

计算机缺少d3dx9_43.dll怎么办?5个方法快速修复d3dx9_43.dll文件

在计算机使用过程中&#xff0c;我们常常会遇到一些错误提示&#xff0c;其中之一就是“d3dx9_43.dll丢失”。这个问题可能会影响到我们的游戏体验或者软件运行。为了解决这个问题&#xff0c;我查阅了一些资料并尝试了多种方法。在这里&#xff0c;我想分享一下我对d3dx9_43.d…...

2023亚太杯数学建模C题思路分析 - 我国新能源电动汽车的发展趋势

1 赛题 问题C 我国新能源电动汽车的发展趋势 新能源汽车是指以先进技术原理、新技术、新结构的非常规汽车燃料为动力来源( 非常规汽车燃料指汽油、柴油以外的燃料&#xff09;&#xff0c;将先进技术进行汽车动力控制和驱动相结 合的汽车。新能源汽车主要包括四种类型&#x…...

c语言新龟兔赛跑

以下是一个使用C语言编写的新的龟兔赛跑游戏&#xff1a; #include <stdio.h>#include <stdlib.h>#include <time.h>int main() { int distance, turtle_speed, rabbit_speed, turtle_time, rabbit_time, rabbit_lead; srand(time(NULL)); // 随机数种…...

Linux驱动开发——网络设备驱动(理论篇)

目录 一、前言 二、网络层次结构 三、网络设备驱动核心数据结构和函数 一、前言 网络设备驱动是 Linux 的第三大类驱动&#xff0c;也是我们学习的最后一类 Linux 驱动。这里我们首先简单学习一下网络协议层次结构&#xff0c;然后简单讨论 Linux 内核中网络实现的层次结构。…...

simulink仿真

1&#xff09;系统问题 连续系统&#xff0c;离散系统&#xff08;采样周期问题&#xff09; 系统分析问题 2&#xff09;求解器问题 变步长&#xff0c;定步长&#xff0c;步长时间与采样周期问题、 3&#xff09;积分器问题 连续积分&#xff0c;离散积分问题&#xff…...

PC端页面进去先出现加载效果

自定义指令v-loading&#xff0c;只需要绑定Boolean即可 v-loading“loading” <el-table :data"list" border style"width: 100%" v-loading"loading"><el-table-column align"center" label"序号" width"5…...

磁盘清理在哪里?学会这4个方法,快速清理内存!

“在使用电脑的过程中&#xff0c;我可能经常会保存一些文件到电脑上&#xff0c;这也导致电脑经常出现内存不足的情况。我想问问磁盘清理在哪里呀&#xff1f;我应该如何打开呢&#xff1f;” 随着使用电脑的时间增长&#xff0c;用户可能经常会遇到磁盘空间不足的情况&#x…...

Error opening terminal: xterm.”的解决方法

主要是看下面这两个变量是否设置正确 $ echo $TERM $ echo $TERMINFO 通常TERM的默认值为xterm-265color, 要查看支持的term&#xff0c;可以ls -al /lib/terminfo/x/ 如果TERM是xterm-265color的话&#xff0c;TERMINFO设置为/usr/lib/terminfo make menuconfig时提示“Err…...

C#常见的设计模式-结构型模式

引言 设计模式是软件工程中用于解决常见问题的可复用解决方案。在C#编程中&#xff0c;常见的设计模式具有广泛的应用。本篇博客将重点介绍C#中常见的结构型设计模式&#xff0c;包括适配器模式、装饰器模式、代理模式、组合模式和享元模式。 目录 引言1. 适配器模式(Adapter …...

Redis分片备库切换操作

Redis分片备库切换操作 场景描述&#xff1a; 分片集群&#xff1a; 1.ipa:5001-ipa:5002 2.ipb:5001-ipb:5002 需将两个分片备库互置完成灾备 操作步骤 准备工作 主机密码&#xff1a;1qaz!QAZ 获取节点信息命令 /redispath/bin/redis-cli -a password -h ip -p port red…...

二叉树:leetcode1457. 二叉树中的伪回文路径

给你一棵二叉树&#xff0c;每个节点的值为 1 到 9 。我们称二叉树中的一条路径是 「伪回文」的&#xff0c;当它满足&#xff1a;路径经过的所有节点值的排列中&#xff0c;存在一个回文序列。 请你返回从根到叶子节点的所有路径中 伪回文 路径的数目。 给定二叉树的节点数目…...

【【Linux下的Petallinux 以及其他的配置】】

Linux下的Petallinux 以及其他的配置 sudo apt-get install iproute2 gawk python3 python build-essential gcc git make net-tools libncurses5-dev tftpd zlib1g-dev libssl-dev flex bison libselinux1 gnupg wget git-core diffstat chrpath socat xterm autoconf libtoo…...

Go 限流器性能优化终极指南:避免缓存伪共享的 padding 策略

Go 限流器性能优化终极指南&#xff1a;避免缓存伪共享的 padding 策略 【免费下载链接】ratelimit A Go blocking leaky-bucket rate limit implementation 项目地址: https://gitcode.com/gh_mirrors/ra/ratelimit 在 Go 高性能限流器开发中&#xff0c;go.uber.org/r…...

C# 13主构造函数到底怎么用:从语法糖到IL底层,3步写出零反射、零冗余的生产级代码

第一章&#xff1a;C# 13主构造函数到底怎么用&#xff1a;从语法糖到IL底层&#xff0c;3步写出零反射、零冗余的生产级代码 C# 13 的主构造函数&#xff08;Primary Constructors&#xff09;并非简单的语法糖&#xff0c;而是编译器在类型声明阶段就完成参数绑定与字段初始化…...

人机之间的有概念交互与无概念交互

人机交互中的“有概念交互”与“无概念交互”&#xff0c;实质上是对人机关系中“显性/有形”与“隐性/无形”双重属性的深度概括。这不仅是技术层面的区分&#xff0c;更涉及人机环境系统中“存在”与“体验”的本质。可以从以下几个维度来解析这两种交互形态&#xff1a;1. 有…...

STM32 GPIO工作模式详解与应用指南

1. STM32 GPIO工作模式深度解析作为一名嵌入式开发工程师&#xff0c;我经常需要与STM32的GPIO打交道。GPIO&#xff08;General Purpose Input/Output&#xff09;作为单片机最基础也最常用的外设&#xff0c;其工作模式的选择直接影响着系统稳定性和功能实现。今天我将结合自…...

Docker镜像拉取超时?5分钟搞定国内镜像源加速配置(附最新可用镜像列表)

Docker镜像加速全攻略&#xff1a;2024国内镜像源配置与疑难排解 每次在终端输入docker pull后盯着进度条卡住不动&#xff0c;是不是感觉血压都在飙升&#xff1f;作为国内开发者&#xff0c;Docker官方镜像源的访问问题就像一场永远打不完的"拉锯战"。但别急着摔键…...

NifSkope终极指南:为什么这款免费开源3D模型编辑器能彻底改变你的游戏模组制作体验

NifSkope终极指南&#xff1a;为什么这款免费开源3D模型编辑器能彻底改变你的游戏模组制作体验 【免费下载链接】nifskope A git repository for nifskope. 项目地址: https://gitcode.com/gh_mirrors/ni/nifskope 你是否曾为《上古卷轴》或《辐射》系列的模型文件格式头…...

基于模型参考自适应系统的改进滑模观测器:反电势优化方法及其仿真模型

基于模型参考自适应系统的改进滑模观测器 1.采用基于模型参考自适应系统的反电势优化方法&#xff0c;对SMO中低通滤波后的反电势进一步优化&#xff0c;从而减小抖振&#xff0c;提高转速和位置估计精度&#xff1b; 2.提供算法对应的参考文献和仿真模型。滑膜观测器这玩意儿在…...

终极指南:如何使用Everything Claude Code实现Laravel验证循环的AI自动化

终极指南&#xff1a;如何使用Everything Claude Code实现Laravel验证循环的AI自动化 【免费下载链接】everything-claude-code The agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, C…...

FireRedASR Pro实战案例:如何将1小时会议录音快速整理成文字稿

FireRedASR Pro实战案例&#xff1a;如何将1小时会议录音快速整理成文字稿 1. 场景痛点与解决方案 1.1 会议记录的传统困境 想象一下这样的场景&#xff1a;公司每周的部门例会刚刚结束&#xff0c;作为会议记录负责人的你&#xff0c;面对长达1小时的录音文件发愁。传统的人…...

ANIMATEDIFF PRO企业级部署:API服务化与WebUI双模式运行指南

ANIMATEDIFF PRO企业级部署&#xff1a;API服务化与WebUI双模式运行指南 1. 项目概述与核心价值 ANIMATEDIFF PRO是一个基于先进AnimateDiff架构的专业级文生视频渲染平台&#xff0c;专为追求电影级视觉效果的内容创作者和AI艺术家设计。这个平台集成了Realistic Vision V5.…...