Spring MVC 父子容器深度解析:原理、实战与优化

1. 父子容器的定义与设计初衷

一句话总结:父子容器的核心价值在于解耦 Web 层与业务层,实现职责分离与上下文隔离。

1.1 父子容器的层次关系

Spring MVC 中,容器分为两类:

  • 父容器(Root ApplicationContext):由 ContextLoaderListener 创建,主要存放 Service、DAO、事务管理器、数据源 等业务相关 Bean。

  • 子容器(WebApplicationContext):由 DispatcherServlet 创建,主要存放 Controller、HandlerMapping、ViewResolver 等 Web 层相关 Bean。

层级关系描述(文字版流程图)

  1. Tomcat 启动,ContextLoaderListener 初始化父容器。

  2. 父容器加载全局 Bean(数据源、事务管理器、业务 Service)。

  3. DispatcherServlet 初始化子容器,并将父容器引用传递给它。

  4. 子容器加载 Web 层 Bean(Controller、ViewResolver)。

  5. Bean 查找规则:先找子容器 → 找不到再去父容器


1.2 生命周期差异

特性父容器(Root)子容器(Web)
创建时机Web 容器启动时每个 DispatcherServlet 启动时
销毁时机Web 容器关闭时对应 Servlet 销毁时
Bean 作用域全局共享仅限当前 Servlet
常见存放对象Service、DAO、事务管理器Controller、视图解析器、拦截器


1.3 单容器 vs 父子容器

对比维度单容器架构父子容器架构
隔离性无隔离,所有 Bean 混在一个容器里Web 层与业务层隔离,减少耦合
可维护性项目大时配置混乱分层清晰,职责明确
启动效率启动慢(所有 Bean 一起加载)可按 Servlet 粒度启动部分 Web 层
适用场景小型单体应用中大型单体应用,多个 Web 模块共享业务层


1.4 为什么要隔离 Web 层与业务层(业务场景)

场景:一个订单管理系统,有两个模块:

  • PC 端订单管理(/pc/order

  • 移动端订单管理(/mobile/order

如果使用 父子容器

  • 订单 Service、DAO、事务管理器放在 父容器,PC 和移动端的 Controller 可以共享它们。

  • 两个模块的 Controller、拦截器、视图配置放在 不同的子容器,互不干扰。


1.5 示例代码:XML 版父子容器

web.xml

<!-- 父容器配置 -->
<context-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring/root-context.xml</param-value>
</context-param>
<listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener><!-- 子容器配置 -->
<servlet><servlet-name>spring-mvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring/servlet-context.xml</param-value></init-param><load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping><servlet-name>spring-mvc</servlet-name><url-pattern>/</url-pattern>
</servlet-mapping>

root-context.xml(父容器)

<context:component-scan base-package="com.example.service, com.example.dao" />
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" />
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/>
</bean>

servlet-context.xml(子容器)

<context:component-scan base-package="com.example.web" />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/WEB-INF/views/" /><property name="suffix" value=".jsp" />
</bean>

2. 父子容器的实现原理

一句话总结:父子容器通过 WebApplicationContext 的层级结构和 Bean 查找链实现单向依赖。


2.1 ContextLoaderListener(父容器)加载流程

源码入口:ContextLoaderListenercontextInitialized()initWebApplicationContext()

流程

  1. 创建 WebApplicationContext 实例(默认 XmlWebApplicationContext)。

  2. contextConfigLocation 读取父容器配置文件。

  3. 调用 refresh() 完成 Bean 加载和初始化。

  4. 将父容器放入 ServletContext,供子容器引用。

简化源码(伪代码):

public WebApplicationContext initWebApplicationContext(ServletContext sc) {WebApplicationContext wac = createWebApplicationContext(sc);configureAndRefresh(wac);sc.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac);return wac;
}

2.2 DispatcherServlet(子容器)加载流程

源码入口:DispatcherServletinitServletBean()initWebApplicationContext()

流程

  1. 创建子容器 WebApplicationContext

  2. contextConfigLocation 读取子容器配置文件。

  3. 调用 setParent() 将父容器引用传入。

  4. 调用 refresh() 初始化 Web 层 Bean。

简化源码(伪代码):

protected WebApplicationContext initWebApplicationContext() {WebApplicationContext parent = WebApplicationContextUtils.getWebApplicationContext(getServletContext());WebApplicationContext wac = createWebApplicationContext(parent);configureAndRefresh(wac);return wac;
}

2.3 Bean 查找机制

WebApplicationContext 继承自 ApplicationContext,其 getBean() 查找规则:

  1. 先在当前容器查找 Bean。

  2. 如果找不到且有父容器,则向父容器递归查找。

  3. 找不到则抛出 NoSuchBeanDefinitionException

    Bean getBean(String name) {if (this.containsBean(name)) {return this.getLocalBean(name);} else if (this.parent != null) {return this.parent.getBean(name);} else {throw new NoSuchBeanDefinitionException(name);}
    }
    

2.4 子容器访问父容器 Bean(示例)

Service(父容器)

@Service
public class OrderService {public void createOrder() {System.out.println("订单创建成功");}
}

Controller(子容器)

@Controller
public class OrderController {@Autowiredprivate OrderService orderService;@RequestMapping("/create")public String createOrder() {orderService.createOrder();return "success";}
}

2.5 深入源码:refresh() 方法调用链

refresh() 是 Spring 容器启动的核心方法,父子容器初始化时都会调用它。无论是 ContextLoaderListener 还是 DispatcherServlet,最终都会走到这里。

核心流程(文字版调用链)

  1. prepareRefresh() — 准备环境变量、校验配置文件、记录启动时间。

  2. obtainFreshBeanFactory() — 创建或刷新 BeanFactory 实例(DefaultListableBeanFactory)。

  3. prepareBeanFactory(beanFactory) — 注册默认的 BeanPostProcessor、环境变量、依赖解析器等。

  4. postProcessBeanFactory(beanFactory) — 模板方法,允许子类扩展(如 AbstractRefreshableWebApplicationContext 会在这里注册 Web 相关 Bean)。

  5. invokeBeanFactoryPostProcessors(beanFactory) — 执行 BeanFactoryPostProcessor(如 ConfigurationClassPostProcessor 解析 @Configuration@ComponentScan)。

  6. registerBeanPostProcessors(beanFactory) — 注册所有 BeanPostProcessor(AOP、@Autowired 等依赖注入的关键)。

  7. initMessageSource() — 初始化国际化资源。

  8. initApplicationEventMulticaster() — 初始化事件广播器。

  9. onRefresh() — 模板方法,Spring MVC 子容器会在这里初始化 HandlerMappingHandlerAdapter 等。

  10. registerListeners() — 注册所有事件监听器。

  11. finishBeanFactoryInitialization(beanFactory) — 实例化所有非懒加载单例 Bean。

  12. finishRefresh() — 发布 ContextRefreshedEvent 事件,标记容器启动完成。

关键源码(简化版)

public void refresh() {synchronized (this.startupShutdownMonitor) {prepareRefresh();ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();prepareBeanFactory(beanFactory);postProcessBeanFactory(beanFactory);invokeBeanFactoryPostProcessors(beanFactory);registerBeanPostProcessors(beanFactory);initMessageSource();initApplicationEventMulticaster();onRefresh(); // Web 容器在这里启动 MVC 组件registerListeners();finishBeanFactoryInitialization(beanFactory);finishRefresh();}
}

2.6 父子容器的 BeanFactory 关系

  • 父容器:DefaultListableBeanFactory

  • 子容器:DefaultListableBeanFactory,但 parentBeanFactory 指向父容器的 BeanFactory

  • 这种设计保证了 子容器可以访问父容器 Bean,但父容器无法访问子容器 Bean。

关系示意(文字版)

Parent BeanFactory (Service, DAO, TransactionManager)↑
Child BeanFactory (Controller, HandlerMapping, ViewResolver)

2.7 业务场景中的 refresh() 应用

假设我们有以下结构:

  • 父容器:DataSourceConfig(数据源)、TransactionConfig(事务管理器)

  • 子容器:WebMvcConfig(Controller、ViewResolver)

启动时:

  1. ContextLoaderListener 调用 refresh() 完成父容器初始化,数据源和事务管理器就绪。

  2. DispatcherServlet 调用 refresh() 初始化子容器,Controller 中通过 @Autowired 获取 Service。

  3. 由于子容器的 BeanFactory parentBeanFactory = 父容器的 BeanFactory,Controller 可以直接注入 Service。


2.8 示例:验证父子容器 Bean 访问规则

// 父容器中的 Bean
@Service
public class ProductService {public String getProductName() {return "MacBook Pro";}
}// 子容器中的 Bean
@Controller
public class ProductController {@Autowiredprivate ProductService productService; // 直接注入父容器的 Bean@RequestMapping("/product")@ResponseBodypublic String product() {return productService.getProductName();}
}

如果你尝试在 父容器的 Bean 中注入子容器的 Controller,会报错:

@Service
public class InvalidService {@Autowiredprivate ProductController controller; // ❌ NoSuchBeanDefinitionException
}

3. 父子容器的配置实践

一句话总结:父子容器配置的核心是职责分层与包路径隔离,确保 Web 层和业务层的 Bean 不会相互污染。


3.1 基于 XML 的配置

3.1.1 web.xml 配置

<!-- 父容器配置(业务层) -->
<context-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring/root-context.xml</param-value>
</context-param>
<listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener><!-- 子容器配置(Web 层) -->
<servlet><servlet-name>spring-mvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring/servlet-context.xml</param-value></init-param><load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping><servlet-name>spring-mvc</servlet-name><url-pattern>/</url-pattern>
</servlet-mapping>

解析

  • contextConfigLocation(父容器)会被 ContextLoaderListenerinitWebApplicationContext() 中读取,然后传给 refresh() 去加载配置。

  • DispatcherServlet 自己的 contextConfigLocation 也是在 initWebApplicationContext() 里读取,并调用 refresh() 初始化子容器。


3.1.2 父容器配置(root-context.xml)

<context:component-scan base-package="com.example.service, com.example.dao" /><bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"><property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/demo"/><property name="username" value="root"/><property name="password" value="123456"/>
</bean><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/>
</bean>

3.1.3 子容器配置(servlet-context.xml)

<context:component-scan base-package="com.example.web" /><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/WEB-INF/views/"/><property name="suffix" value=".jsp"/>
</bean>

3.2 基于 Java Config 的配置

3.2.1 父容器配置

@Configuration
@ComponentScan(basePackages = {"com.example.service", "com.example.dao"}
)
public class RootConfig {@Beanpublic DataSource dataSource() {BasicDataSource ds = new BasicDataSource();ds.setDriverClassName("com.mysql.cj.jdbc.Driver");ds.setUrl("jdbc:mysql://localhost:3306/demo");ds.setUsername("root");ds.setPassword("123456");return ds;}@Beanpublic PlatformTransactionManager transactionManager(DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}
}

3.2.2 子容器配置

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"com.example.web"},excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = Service.class // 排除业务层)
)
public class WebConfig implements WebMvcConfigurer {@Beanpublic ViewResolver viewResolver() {InternalResourceViewResolver vr = new InternalResourceViewResolver();vr.setPrefix("/WEB-INF/views/");vr.setSuffix(".jsp");return vr;}
}

3.3 包隔离策略

为了确保父子容器的 Bean 空间不冲突,建议:

  1. 业务层包路径com.example.service, com.example.dao

  2. Web 层包路径com.example.web

  3. 父容器的 @ComponentScan 不要扫描 com.example.web

  4. 子容器的 @ComponentScan 使用 excludeFilters 排除业务层包


3.4 业务场景示例

场景:PC 端和移动端共用业务逻辑,但 UI 层不同。

  • 父容器放:OrderService, ProductService

  • PC 子容器放:PcOrderController

  • Mobile 子容器放:MobileOrderController

好处:

  • 两个子容器都能调用相同的 OrderService

  • 修改 PC 端 Controller 不会影响移动端 Controller

  • 启动时可以单独加载一个子容器进行测试

4. 父子容器的应用场景与局限性

一句话总结:父子容器非常适合中大型单体应用的分层管理,但在微服务场景中可能会被替代。


4.1 典型应用场景

场景 1:多个 Web 模块共享业务逻辑

假设一个企业系统有:

  • 后台管理模块(/admin)

  • 前台门户模块(/portal)

父容器

  • UserService

  • ProductService

  • DataSource

  • TransactionManager

子容器

  • admin 子容器:AdminControllerAdminInterceptor

  • portal 子容器:PortalControllerPortalInterceptor

好处:

  • Service 和 DAO 只加载一次,节省内存

  • 控制器互不干扰,职责分离


场景 2:多 DispatcherServlet 的多语言站点

  • /en/* → English 子容器

  • /cn/* → Chinese 子容器

  • 公共业务逻辑放在父容器


4.2 事务管理器必须放在父容器的原因

原因:事务管理器通常会在 Service 层通过 @Transactional 生效,而 @Transactional 的底层依赖于 AOP 代理,代理对象的生成需要在 业务 Bean 初始化阶段完成。
如果事务管理器放在子容器:

  1. 父容器初始化 Service 时找不到事务管理器 Bean(因为父容器无法向下访问子容器)。

  2. 事务增强器 BeanFactoryTransactionAttributeSourceAdvisor 无法正常创建代理对象,导致事务失效。

简化源码片段(事务增强器注册过程):

public class ProxyTransactionManagementConfiguration {@Beanpublic BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(...) {// 需要获取事务管理器 Bean}
}

因为这个 Bean 注册发生在父容器 refresh() 阶段,所以事务管理器必须提前在父容器中准备好。


4.3 常见问题

问题 1:Bean 覆盖

如果父子容器中有相同名称的 Bean,子容器会优先返回自己的 Bean。

// 父容器
@Bean("productService")
public ProductService productServiceV1() { ... }// 子容器
@Bean("productService")
public ProductService productServiceV2() { ... }

结果:Controller 注入的是子容器版本。

解决方法:

  • 使用 @Primary 明确优先级

  • 或者使用 @Qualifier 指定 Bean 名称


问题 2:依赖冲突

  • 子容器中扫描到的 Bean 如果引用了父容器不存在的依赖,会导致启动失败。

  • 避免在 Service 层直接引用 Controller


4.4 在微服务架构中的适用性

  • 在微服务(如 Spring Boot + Spring Cloud)中,每个服务本质上都是一个独立的 ApplicationContext,父子容器的概念意义不大。

  • 替代方案:

    • 通过 API Gateway 和 Feign Client 进行模块解耦

    • 使用共享依赖库(JAR)来复用业务逻辑


4.5 示例:父容器中的事务管理器配置

RootConfig.java

@Configuration
@ComponentScan(basePackages = {"com.example.service", "com.example.dao"})
@EnableTransactionManagement
public class RootConfig {@Beanpublic DataSource dataSource() {BasicDataSource ds = new BasicDataSource();ds.setDriverClassName("com.mysql.cj.jdbc.Driver");ds.setUrl("jdbc:mysql://localhost:3306/demo");ds.setUsername("root");ds.setPassword("123456");return ds;}@Beanpublic PlatformTransactionManager transactionManager(DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}
}

OrderService.java

@Service
public class OrderService {@Transactionalpublic void createOrder() {System.out.println("事务开始:创建订单");// 数据库操作...}
}

OrderController.java

@Controller
public class OrderController {@Autowiredprivate OrderService orderService;@RequestMapping("/order")@ResponseBodypublic String order() {orderService.createOrder(); // 事务生效return "success";}
}

5. 父子容器的进阶优化


5.1 使用 WebApplicationInitializer 手动创建父子容器

Spring MVC 默认是通过 ContextLoaderListener 创建父容器,再由 DispatcherServlet 创建子容器。
我们可以用 Java Config 全程替代 XML,并且手动精确控制父子容器的关系。

示例代码

public class MyWebAppInitializer implements WebApplicationInitializer {@Overridepublic void onStartup(ServletContext servletContext) throws ServletException {// 1. 创建父容器AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();rootContext.register(RootConfig.class);servletContext.addListener(new ContextLoaderListener(rootContext));// 2. 创建子容器(DispatcherServlet 专用)AnnotationConfigWebApplicationContext mvcContext = new AnnotationConfigWebApplicationContext();mvcContext.register(WebMvcConfig.class);ServletRegistration.Dynamic dispatcher =servletContext.addServlet("dispatcher", new DispatcherServlet(mvcContext));dispatcher.setLoadOnStartup(1);dispatcher.addMapping("/");}
}

核心好处

  • 父子容器的边界由你自己定义

  • 可以注册多个 DispatcherServlet,每个都有独立的子容器

  • 可以在父容器创建前做预处理(如动态加载配置文件)


5.2 父子容器 Bean 冲突优化

在开发中,父子容器如果不加规则,很容易出现 Bean 名称冲突问题。

解决策略

  1. 命名空间法

    • 父容器所有 Bean 以 core* 开头

    • 子容器 Bean 以 web* 开头
      这样在注入时几乎不会冲突

  2. @Primary
    标记优先被注入的 Bean

    @Bean
    @Primary
    public ProductService newProductService() { ... }
    
  3. @Qualifier
    明确注入指定 Bean 名称


5.3 事务与 AOP 跨容器优化

当事务涉及多个子容器的 Controller 时,有两个注意点:

  • 事务必须放在父容器

    • 否则子容器 Controller 调用父容器 Service 时可能找不到事务增强器

  • AOP 切面建议也放在父容器

    • 避免每个子容器重复创建切面 Bean

示例:切面放在父容器

@Aspect
@Component
public class LogAspect {@Before("execution(* com.example.service.*.*(..))")public void logBefore() {System.out.println("调用 Service 前记录日志");}
}

5.4 Spring Boot 中的父子容器简化策略

Spring Boot 虽然默认是单容器,但仍然可以模拟父子容器:

  • 父容器:SpringApplicationBuilder 的第一个 sources()

  • 子容器:child() 方法

示例:Boot 模拟父子容器

new SpringApplicationBuilder(ParentConfig.class).child(WebConfig.class).run(args);

这样可以在 Boot 项目中仍然使用父子容器分层结构,但更轻量。


5.5 性能与维护建议

  • 性能优化

    • 父容器只加载一次,不要放和 Web 强绑定的 Bean

    • 子容器尽量只扫描 Controller、拦截器等 Web 组件

  • 维护优化

    • 清晰标注哪些类属于父容器、哪些属于子容器

    • 在多模块项目中,将父容器 Bean 放到独立的 core 模块,子容器 Bean 放到 web 模块

6. 父子容器的源码解析


6.1 创建父容器:ContextLoaderListener

当 Web 容器启动时,ContextLoaderListener 会先调用:

public void contextInitialized(ServletContextEvent event) {initWebApplicationContext(event.getServletContext());
}

这里核心步骤:

  1. 创建 WebApplicationContext(通常是 XmlWebApplicationContextAnnotationConfigWebApplicationContext

  2. 调用 configureAndRefreshWebApplicationContext()

    • 设置配置文件位置

    • 调用 refresh() 初始化所有 Bean


6.2 创建子容器:DispatcherServlet

DispatcherServletinit() 方法中:

this.webApplicationContext = initWebApplicationContext();

initWebApplicationContext() 核心:

  1. 如果没有传入外部的 WebApplicationContext,就自己创建一个

  2. 调用 setParent(parentContext) 将父容器传进来

  3. 调用 refresh() 初始化子容器 Bean


6.3 Bean 查找的向上链路

当你在子容器中调用:

ctx.getBean("xxx");

执行流程:

  1. 在子容器的 beanFactory 查找 BeanDefinition

  2. 如果没找到,就调用:

    if (this.parent != null) {return this.parent.getBean(name, requiredType);
    }
    
  3. 这样会递归向父容器查找,直到顶层容器或抛出异常


6.4 时序图(简化版)

[Servlet 容器启动]↓
ContextLoaderListener -------------------------------| 创建父容器| refresh() 父容器↓
DispatcherServlet -----------------------------------| 创建子容器| setParent(父容器)| refresh() 子容器↓
运行中:getBean() → 子容器→ 父容器→ 祖先容器...

6.5 为什么理解调用链很重要

  • 调试问题
    当出现 "NoSuchBeanDefinitionException" 时,你能立刻判断是子容器没扫描到,还是父容器没加载

  • 性能优化
    你知道哪些 Bean 会被多个子容器共享,就应该放到父容器避免重复初始化

  • 扩展能力
    可以自己写 WebApplicationInitializer 精准控制父子容器的生命周期

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

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

相关文章

AI赋能SEO关键词优化策略

内容概要 人工智能&#xff08;AI&#xff09;技术正深刻改变着搜索引擎优化&#xff08;SEO&#xff09;的实践方式&#xff0c;尤其在关键词研究这一核心领域带来了革命性的影响。本文聚焦于AI如何赋能SEO关键词优化策略&#xff0c;系统性地探讨其核心价值与应用路径。我们将…

虚拟机Ubuntu图形化界面root用户登录错误

当在 Ubuntu 图形界面登录 root 用户出现错误无法进入时 1. 检查 PAM 配置文件 PAM&#xff08;Pluggable Authentication Modules&#xff0c;可插拔认证模块&#xff09;负责管理用户认证相关的策略。图形登录界面的 PAM 配置文件通常是 /etc/pam.d/gdm-password 。以管理员权…

【杂谈】-逆缩放悖论:为何更多思考会让AI变“笨“?

逆缩放悖论&#xff1a;为何更多思考会让AI变"笨"&#xff1f; 文章目录逆缩放悖论&#xff1a;为何更多思考会让AI变"笨"&#xff1f;1、解码逆缩放现象2、AI 推理失效的五大症结3、AI 推理应对复杂度的策略图谱4、人工智能评估体系的反思5、人工智能推理…

强制用户更改WordPress密码的重要性及实现方法

确保 WordPress 网站的安全性是每位网站管理者的重要任务。在网络安全日益受到关注的今天&#xff0c;为用户提供安全、稳定的网络环境至关重要。而一个有效的方法就是强制用户定期更改密码。这篇文章将介绍为什么要强制用户更改密码以及如何在 WordPress 中实现这一功能。同时…

计算机基础速通--数据结构·串的应用

如有问题大概率是我的理解比较片面&#xff0c;欢迎评论区或者私信指正。 友友们&#xff0c;我遇到了一个大问题&#xff0c;技术类的英文面&#xff08;ai应用开发/java后端偏金融方向&#xff09;该如何准备&#xff1f;本人英语就过了个六级&#xff0c;脑阔疼额。友友们有…

05--STL认识(了解)

1. STL概念——标准模板库 STL(standard template libaray-标准模板库)&#xff1a;是C标准库的重要组成部分&#xff0c;不仅是一个可复用的组件库&#xff0c;而且是一个包罗数据结构与算法的软件框架。 STL与CPP标准库的关系&#xff1a; 2. STL的版本 3. STL的组成 4. STL…

VBA经典应用69例应用9:ReDim语句的语法

《VBA经典应用69例》&#xff08;版权10178981&#xff09;&#xff0c;是我推出的第九套教程&#xff0c;教程是专门针对初级、中级学员在学习VBA过程中可能遇到的案例展开&#xff0c;这套教程案例众多&#xff0c;紧贴“实战”&#xff0c;并做“战术总结”&#xff0c;以便…

连锁店管理系统的库存跟踪功能:数字化转型下的零售运营核心

在连锁零售行业&#xff0c;库存管理的效率直接决定着运营成败。传统人工库存管理模式早已难以应对全渠道销售时代的复杂需求&#xff0c;而连锁店管理系统的库存跟踪功能&#xff0c;正成为解决库存难题、提升客户体验的关键武器。本文将深入解析施易德&#xff08;cegid&…

Nestjs框架: 接口安全与响应脱敏实践 --- 从拦截器到自定义序列化装饰器

接口安全问题&#xff1a;敏感数据脱敏的必要性 在用户注册成功后&#xff0c;若直接将用户数据&#xff08;如密码、ID 等&#xff09;返回给前端&#xff0c;存在严重的安全风险 为此&#xff0c;需要在接口响应前对数据进行脱敏处理 关键点&#xff1a; 敏感字段&#xff…

Python包与虚拟环境工具全景对比:从virtualenv到uv的演进

Python 的开发环境管理一直是综合性的工程问题。随着工具和规范的不断进化&#xff0c;我们看到了从 virtualenv / pip 开始&#xff0c;到 pipenv 和 poetry 的环境一体化&#xff0c;再到 uv 和 hatch 这样的一体化、高性能新生代工具。 本文将对比这些工具的特点、优势和选型…

期货和期权对冲后能盈利吗?

本文主要介绍期货和期权对冲后能盈利吗&#xff1f;期货和期权作为金融衍生品的两大核心工具&#xff0c;其组合对冲策略的盈利性取决于市场走势、策略设计、成本管控及风险对冲效果。对冲的本质是降低风险&#xff0c;但通过合理设计&#xff0c;部分策略可在对冲风险的同时创…

【其他分类】Showrunner AI版的Netflix 互动故事创作平台 进行动画生成与微调、角色场景创建

Showrunner是一个AI 驱动的角色场景动画。视觉风格较为统一&#xff0c;偏向 3D Q 版卡通风格&#xff0c;支持语音对白修改、镜头相机切换、动画角色和场景设置等功能。 论文原文中文翻译官方地址pdf版 、网页版pdf版https://www.showrunner.xyz/ 当前的2D 动画软件&#xff…

K8s 常见故障案例分析

#作者&#xff1a;程宏斌 文章目录一、节点故障&#xff08;一&#xff09;节点 NotReady 状态排查步骤解决方案二、Pod 故障&#xff08;一&#xff09;Pod 一直处于 Pending 状态排查步骤解决方案&#xff08;二&#xff09;Pod 频繁重启故障现象排查步骤解决方案三、控制器故…

半精度权重 及 Phi-3线性层的权重分布

半精度权重 我们可以使用张量的 to() 方法以及适当的类型 torch.float16,将权重转换为 FP16: torch.manual_seed(11) weights = torch.randn(1000) * .07 weights.min(),

Linux怎么安装Docker?环境怎么搭建?步骤是什么?如何配置?有哪些注意事项?出现问题怎么排除?

一、Docker简介与环境准备 1.1 什么是Docker Docker是一个开源的容器化平台&#xff0c;它使用Linux内核的cgroup&#xff0c;namespace以及OverlayFS类的UnionFS等技术&#xff0c;对进程进行封装隔离&#xff0c;属于操作系统层面的虚拟化技术。Docker能够自动执行重复性任务…

apiSQL网关调优:释放单节点的最大潜能

前言 在构建高性能、高可用的API服务时&#xff0c;apiSQL 提供了强大的集群部署模式&#xff0c;通过横向扩展来分散负载、提高吞吐量。然而&#xff0c;在某些场景下&#xff0c;我们同样需要关注并最大化单个节点的处理能力。当单个 apiSQL 网关节点需要处理高并发请求或承载…

【开源工具】网络交换机批量配置生成工具开发全解:从原理到实战(附完整Python源码)

🔥 【开源工具】网络交换机批量配置生成工具开发全解:从原理到实战(附完整Python源码) 🌈 个人主页:创客白泽 - CSDN博客 🔥 系列专栏:🐍《Python开源项目实战》 💡 热爱不止于代码,热情源自每一个灵感闪现的夜晚。愿以开源之火,点亮前行之路。 🐋 希望大家…

【插件式微服务架构系统分享】之 解耦至上:gateway 网关与APISIX 网关的不同分工

【插件式微服务架构系统分享】之解耦至上&#xff1a;gateway 网关与APISIX 网关的不同分工作者&#xff1a;朱元禄一、一个比方 APISIX 就像是一个专业的高速公路收费站&#xff0c;不属于你公司自己造的路&#xff0c;而是专门为所有车辆&#xff08;流量&#xff09;设计的&…

【感知机】感知机(perceptron)学习算法例题及详解

感知机( perceptron )是二类分类的线性分类模型&#xff0c;其输入为实例的特征向量&#xff0c;输出为实例的类别&#xff0c;取1 和-1二值。感知机对应输入空间(特征空间)中将实例划分为正负两类的分离超平面&#xff0c;是一种判别模型。感知机是神经网络与支持向量机的基础…

Linux基础命令速查:从入门到精通

Linux常用命令指南一、操作系统概述1 . 什么是操作系统&#xff1f;2. 为什么需要操作系统&#xff1f;二、Linux基础命令1. 目录与文件操作2. 文件操作命令3. 文件查看命令4. 文本处理命令三、重定向1. 重定向符号四、Linux系统概念1. 文件系统特点2. 路径规则3. 通配符五、压…