Spring Boot 的自动配置,以rabbitmq为例,请详细说明
Spring Boot 的自动配置特性能够大大简化集成外部服务和组件的配置过程。以 RabbitMQ 为例,Spring Boot 通过 spring-boot-starter-amqp
提供了自动配置支持,开发者只需在应用中添加相关依赖并配置必要的属性,Spring Boot 会自动配置所需的连接工厂、消息队列、交换机、消息模板等。
以下是以 RabbitMQ 为例的详细说明。
1. 引入 RabbitMQ 依赖
要使用 Spring Boot 集成 RabbitMQ,首先需要在项目的 pom.xml
文件中添加 spring-boot-starter-amqp
依赖,这个依赖包含了与 RabbitMQ 交互的所有必要组件。
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
spring-boot-starter-amqp
依赖包含了 Spring AMQP
和 RabbitMQ
的连接组件,自动配置会根据此依赖自动启用 RabbitMQ 相关功能。
2. 配置 RabbitMQ 连接属性
接下来,你需要在 application.properties
或 application.yml
中配置 RabbitMQ 的连接信息。例如:
使用 application.properties
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.virtual-host=/
spring.rabbitmq.publisher-confirm-type=simple
spring.rabbitmq.listener.simple.concurrency=3
spring.rabbitmq.listener.simple.max-concurrency=10
spring.rabbitmq.host
:RabbitMQ 服务器的地址,通常是localhost
。spring.rabbitmq.port
:RabbitMQ 服务器的端口,默认是5672
。spring.rabbitmq.username
和spring.rabbitmq.password
:RabbitMQ 的认证信息。spring.rabbitmq.virtual-host
:虚拟主机,通常是/
。spring.rabbitmq.publisher-confirm-type
:确认模式,simple
为简单确认。spring.rabbitmq.listener.simple.concurrency
:并发消费者数量。spring.rabbitmq.listener.simple.max-concurrency
:最大消费者数量。
Spring Boot 会读取这些配置并自动配置连接工厂、消息队列监听器等。
3. 自动配置的原理
Spring Boot 在启动时会通过 spring-boot-autoconfigure
模块自动配置 RabbitMQ 相关的 Bean,主要通过以下几个步骤:
3.1 自动配置连接工厂(ConnectionFactory
)
Spring Boot 会根据 spring.rabbitmq.*
配置自动创建一个 ConnectionFactory
,它负责与 RabbitMQ 服务器建立连接。通常,Spring Boot 默认使用 CachingConnectionFactory
来实现连接工厂。
@Bean
@Primary
@ConditionalOnMissingBean(ConnectionFactory.class)
public CachingConnectionFactory connectionFactory() {CachingConnectionFactory connectionFactory = new CachingConnectionFactory();connectionFactory.setHost(rabbitProperties.getHost());connectionFactory.setPort(rabbitProperties.getPort());connectionFactory.setUsername(rabbitProperties.getUsername());connectionFactory.setPassword(rabbitProperties.getPassword());connectionFactory.setVirtualHost(rabbitProperties.getVirtualHost());return connectionFactory;
}
@ConditionalOnMissingBean
表示如果应用上下文中没有ConnectionFactory
的 Bean,Spring Boot 会创建一个默认的CachingConnectionFactory
。- 配置的
spring.rabbitmq.*
参数将被注入到这个ConnectionFactory
中。
3.2 自动配置 RabbitTemplate
RabbitTemplate
是 Spring AMQP 用来发送消息的核心类。Spring Boot 会自动配置一个 RabbitTemplate
,它使用 ConnectionFactory
来与 RabbitMQ 服务器进行交互。
@Bean
@ConditionalOnMissingBean(RabbitTemplate.class)
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {RabbitTemplate template = new RabbitTemplate(connectionFactory);template.setMessageConverter(new Jackson2JsonMessageConverter());return template;
}
RabbitTemplate
被用来发送消息,Spring Boot 自动创建并配置。- 默认使用 JSON 消息转换器(
Jackson2JsonMessageConverter
)将消息转换为 JSON 格式。
3.3 自动配置 RabbitListenerContainerFactory
如果你想使用 @RabbitListener
注解来监听 RabbitMQ 消息队列,Spring Boot 会自动配置 RabbitListenerContainerFactory
。
@Bean
@ConditionalOnMissingBean(RabbitListenerContainerFactory.class)
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory, RabbitProperties rabbitProperties) {SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();factory.setConnectionFactory(connectionFactory);factory.setConcurrency(rabbitProperties.getListener().getSimple().getConcurrency());factory.setMaxConcurrency(rabbitProperties.getListener().getSimple().getMaxConcurrency());return factory;
}
- 这个工厂用于创建 RabbitMQ 消息监听容器,容器负责消费队列中的消息。
setConcurrency
和setMaxConcurrency
用来配置消息消费者的并发数。
3.4 自动配置消息监听器(@RabbitListener
)
Spring Boot 会自动启用对 @RabbitListener
注解的支持。你可以使用 @RabbitListener
注解创建消息监听器,而无需手动配置监听容器。
4. 创建消费者和生产者
4.1 消息生产者(发送消息)
你可以使用 RabbitTemplate
发送消息到 RabbitMQ 队列。
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class MessageProducer {@Autowiredprivate RabbitTemplate rabbitTemplate;public void sendMessage(String message) {rabbitTemplate.convertAndSend("myQueue", message);}
}
rabbitTemplate.convertAndSend
方法用于将消息发送到指定的队列(myQueue
)。- Spring Boot 会自动为你配置队列、交换机、路由等。
4.2 消息消费者(监听消息)
你可以使用 @RabbitListener
注解来创建消息消费者,监听指定的队列,并在消息到达时处理它。
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;@Service
public class MessageConsumer {@RabbitListener(queues = "myQueue")public void receiveMessage(String message) {System.out.println("Received message: " + message);}
}
@RabbitListener
注解会告诉 Spring Boot 自动创建一个消息监听器并连接到指定的队列。- 每当有消息进入
myQueue
队列时,receiveMessage
方法就会被调用。
5. 自定义配置
你可以进一步自定义 RabbitMQ 的配置,以下是一些常见的自定义场景:
5.1 配置交换机、队列和绑定
你可以定义自己的交换机、队列和绑定,确保它们符合你的应用需求。例如:
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class RabbitConfig {@Beanpublic Queue myQueue() {return new Queue("myQueue", true);}@Beanpublic TopicExchange exchange() {return new TopicExchange("myExchange");}@Beanpublic Binding binding(Queue myQueue, TopicExchange exchange) {return BindingBuilder.bind(myQueue).to(exchange).with("myQueue.#");}
}
Queue
定义了一个消息队列。TopicExchange
定义了一个交换机。Binding
定义了队列和交换机之间的绑定关系。
5.2 配置消息监听器的并发
你可以通过 application.properties
或 application.yml
来调整消息监听器的并发配置:
spring.rabbitmq.listener.simple.concurrency=5
spring.rabbitmq.listener.simple.max-concurrency=10
这将允许 Spring Boot 动态调整消费者线程的数量,确保队列消息能够高效消费。
总结
Spring Boot 通过自动配置 RabbitMQ 连接、消息发送和消费等相关组件,极大地简化了 RabbitMQ 的集成过程。只需添加 spring-boot-starter-amqp
依赖并在配置文件中指定必要的参数,Spring Boot 就会自动配置所需的所有组件,并根据需求自动启动消息生产者和消费者。你可以通过注解 @RabbitListener
来定义消息监听器,也可以自定义交换机、队列和绑定等配置,从而满足不同的业务需求。
通过源码再次,详细说明
要深入了解 Spring Boot 如何通过自动配置集成 RabbitMQ,我们需要通过源码分析它是如何工作的。Spring Boot 使用了 spring-boot-starter-amqp
来简化 RabbitMQ 的配置。以下是从源代码角度对 Spring Boot 如何自动配置 RabbitMQ 进行详细说明的过程。
1. Spring Boot 启动流程和自动配置
Spring Boot 使用了 @EnableAutoConfiguration
注解和 spring.factories
文件来实现自动配置。在启动时,Spring Boot 会扫描并自动配置与应用上下文相关的配置类。RabbitMQ 的自动配置就是通过这些配置类实现的。
1.1 spring-boot-starter-amqp
依赖
首先,spring-boot-starter-amqp
依赖包含了 Spring AMQP 和 RabbitMQ 的集成依赖,并提供了 RabbitMQ 自动配置的支持。它的 spring.factories
文件列出了与 RabbitMQ 相关的自动配置类。
在 spring-boot-starter-amqp
中,spring.factories
文件会自动引入 RabbitAutoConfiguration
类。你可以在 spring-boot-starter-amqp
依赖中看到这一点:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
当你引入了这个依赖后,Spring Boot 会自动加载 RabbitMQ 的相关配置。
2. RabbitAutoConfiguration
类
Spring Boot 的 RabbitMQ 自动配置类是 RabbitAutoConfiguration
,它位于 org.springframework.boot.autoconfigure.amqp
包中。这个类的作用是基于你的配置自动设置 RabbitMQ 连接、队列、交换机等。
我们来分析一下 RabbitAutoConfiguration
类的源码:
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(CachingConnectionFactory.class)
@ConditionalOnProperty(prefix = "spring.rabbitmq", name = "host")
@EnableConfigurationProperties(RabbitProperties.class)
@Import({ RabbitListenerConfiguration.class, RabbitManagementConfigurer.class })
public class RabbitAutoConfiguration {private static final Logger logger = LoggerFactory.getLogger(RabbitAutoConfiguration.class);private final RabbitProperties properties;public RabbitAutoConfiguration(RabbitProperties properties) {this.properties = properties;}@Bean@ConditionalOnMissingBean(ConnectionFactory.class)public CachingConnectionFactory connectionFactory() {logger.debug("Creating CachingConnectionFactory");CachingConnectionFactory factory = new CachingConnectionFactory();factory.setHost(this.properties.getHost());factory.setPort(this.properties.getPort());factory.setUsername(this.properties.getUsername());factory.setPassword(this.properties.getPassword());factory.setVirtualHost(this.properties.getVirtualHost());return factory;}@Bean@ConditionalOnMissingBean(RabbitTemplate.class)public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());return rabbitTemplate;}@Bean@ConditionalOnMissingBean(SimpleRabbitListenerContainerFactory.class)public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory, RabbitProperties rabbitProperties) {SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();factory.setConnectionFactory(connectionFactory);factory.setConcurrency(rabbitProperties.getListener().getSimple().getConcurrency());factory.setMaxConcurrency(rabbitProperties.getListener().getSimple().getMaxConcurrency());return factory;}
}
2.1 @Configuration
和 @EnableConfigurationProperties
@Configuration(proxyBeanMethods = false)
:这是一个配置类,proxyBeanMethods = false
表示这个配置类不会使用代理,也就是说,它只会影响当前类中定义的 bean。@EnableConfigurationProperties(RabbitProperties.class)
:该注解使得RabbitProperties
类成为一个配置属性类,允许 Spring Boot 自动加载配置文件中的spring.rabbitmq.*
属性,并将它们绑定到RabbitProperties
对象。
2.2 connectionFactory
Bean
@Bean
@ConditionalOnMissingBean(ConnectionFactory.class)
public CachingConnectionFactory connectionFactory() {CachingConnectionFactory factory = new CachingConnectionFactory();factory.setHost(this.properties.getHost());factory.setPort(this.properties.getPort());factory.setUsername(this.properties.getUsername());factory.setPassword(this.properties.getPassword());factory.setVirtualHost(this.properties.getVirtualHost());return factory;
}
@ConditionalOnMissingBean(ConnectionFactory.class)
:这表示如果应用上下文中没有ConnectionFactory
类型的 Bean,Spring Boot 会自动创建一个CachingConnectionFactory
的实例。CachingConnectionFactory
是 Spring AMQP 提供的一个连接工厂实现,它能缓存到 RabbitMQ 的连接以提高性能。factory.setHost
等:这些配置项通过RabbitProperties
类从application.properties
或application.yml
中读取并注入。
2.3 rabbitTemplate
Bean
@Bean
@ConditionalOnMissingBean(RabbitTemplate.class)
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());return rabbitTemplate;
}
@ConditionalOnMissingBean(RabbitTemplate.class)
:如果RabbitTemplate
已经存在于应用上下文中,Spring Boot 就不会再次创建它。RabbitTemplate
:它是与 RabbitMQ 交互的核心类,主要用于发送消息。Spring Boot 会自动创建并配置RabbitTemplate
,并将其与上面创建的ConnectionFactory
关联。
2.4 rabbitListenerContainerFactory
Bean
@Bean
@ConditionalOnMissingBean(SimpleRabbitListenerContainerFactory.class)
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory, RabbitProperties rabbitProperties) {SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();factory.setConnectionFactory(connectionFactory);factory.setConcurrency(rabbitProperties.getListener().getSimple().getConcurrency());factory.setMaxConcurrency(rabbitProperties.getListener().getSimple().getMaxConcurrency());return factory;
}
SimpleRabbitListenerContainerFactory
:这是一个用来创建 RabbitMQ 消息监听容器的工厂。该容器负责从 RabbitMQ 中接收并处理消息。setConcurrency
和setMaxConcurrency
:这两个方法控制监听器的并发性,指定了消息监听的最小和最大并发数。
3. RabbitListenerConfiguration
和 RabbitManagementConfigurer
RabbitAutoConfiguration
类还通过 @Import
注解引入了 RabbitListenerConfiguration
和 RabbitManagementConfigurer
类。这些类负责配置消息监听器和管理接口等。
java
@Import({ RabbitListenerConfiguration.class, RabbitManagementConfigurer.class })
RabbitListenerConfiguration
:负责配置和启用@RabbitListener
注解的处理。RabbitManagementConfigurer
:负责 RabbitMQ 管理的配置,通常是为了启用或配置 RabbitMQ 管理界面。
4. RabbitProperties
类
RabbitProperties
类是用来封装 application.properties
或 application.yml
中与 RabbitMQ 相关的配置项的。它的主要作用是将这些配置绑定到 Java 对象上,方便后续使用。
@ConfigurationProperties(prefix = "spring.rabbitmq")
public class RabbitProperties {private String host = "localhost";private int port = 5672;private String username = "guest";private String password = "guest";private String virtualHost = "/";private Listener listener = new Listener();public static class Listener {private Simple simple = new Simple();public static class Simple {private int concurrency = 1;private int maxConcurrency = 1;}}// getters and setters
}
RabbitProperties
是一个 POJO 类,Spring Boot 会将 application.properties
中以 spring.rabbitmq.*
开头的属性自动映射到这个类的字段中。
5. @RabbitListener
注解支持
Spring Boot 自动配置还会启用 @RabbitListener
注解的支持,这意味着你可以通过注解驱动的方式来创建 RabbitMQ 消息监听器。例如:
@Service
public class MyListener {@RabbitListener(queues = "myQueue")public void handleMessage(String message) {System.out.println("Received message: " + message);}
}
6. 总结
通过 RabbitAutoConfiguration
,Spring Boot 自动配置了与 RabbitMQ 交互所需的主要组件:ConnectionFactory
、RabbitTemplate
、SimpleRabbitListenerContainerFactory
等。这些组件的创建是基于 application.properties
中的配置完成的。通过 Spring Boot 的自动配置,开发者只需要添加必要的依赖和配置,不必手动创建和配置这些复杂的 RabbitMQ 组件。
自动配置总结
- ConnectionFactory:用于连接到 RabbitMQ 服务。
- RabbitTemplate:用于发送消息。
- SimpleRabbitListenerContainerFactory:用于配置消息监听容器。
- RabbitListener 注解:用于处理消息监听。
RabbitAutoConfiguration 源码 1.5.9版本
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package org.springframework.boot.autoconfigure.amqp;import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.AmqpAdmin;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.connection.RabbitConnectionFactoryBean;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitMessagingTemplate;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.amqp.RabbitProperties.Retry;
import org.springframework.boot.autoconfigure.amqp.RabbitProperties.Ssl;
import org.springframework.boot.autoconfigure.amqp.RabbitProperties.Template;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.retry.backoff.ExponentialBackOffPolicy;
import org.springframework.retry.policy.SimpleRetryPolicy;
import org.springframework.retry.support.RetryTemplate;@Configuration
@ConditionalOnClass({RabbitTemplate.class, Channel.class})
@EnableConfigurationProperties({RabbitProperties.class})
@Import({RabbitAnnotationDrivenConfiguration.class})
public class RabbitAutoConfiguration {public RabbitAutoConfiguration() {}@Configuration@ConditionalOnClass({RabbitMessagingTemplate.class})@ConditionalOnMissingBean({RabbitMessagingTemplate.class})@Import({RabbitAutoConfiguration.RabbitTemplateConfiguration.class})protected static class MessagingTemplateConfiguration {protected MessagingTemplateConfiguration() {}@Bean@ConditionalOnSingleCandidate(RabbitTemplate.class)public RabbitMessagingTemplate rabbitMessagingTemplate(RabbitTemplate rabbitTemplate) {return new RabbitMessagingTemplate(rabbitTemplate);}}@Configuration@Import({RabbitAutoConfiguration.RabbitConnectionFactoryCreator.class})protected static class RabbitTemplateConfiguration {private final ObjectProvider<MessageConverter> messageConverter;private final RabbitProperties properties;public RabbitTemplateConfiguration(ObjectProvider<MessageConverter> messageConverter, RabbitProperties properties) {this.messageConverter = messageConverter;this.properties = properties;}@Bean@ConditionalOnSingleCandidate(ConnectionFactory.class)@ConditionalOnMissingBean({RabbitTemplate.class})public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);MessageConverter messageConverter = (MessageConverter)this.messageConverter.getIfUnique();if (messageConverter != null) {rabbitTemplate.setMessageConverter(messageConverter);}rabbitTemplate.setMandatory(this.determineMandatoryFlag());Template templateProperties = this.properties.getTemplate();Retry retryProperties = templateProperties.getRetry();if (retryProperties.isEnabled()) {rabbitTemplate.setRetryTemplate(this.createRetryTemplate(retryProperties));}if (templateProperties.getReceiveTimeout() != null) {rabbitTemplate.setReceiveTimeout(templateProperties.getReceiveTimeout());}if (templateProperties.getReplyTimeout() != null) {rabbitTemplate.setReplyTimeout(templateProperties.getReplyTimeout());}return rabbitTemplate;}private boolean determineMandatoryFlag() {Boolean mandatory = this.properties.getTemplate().getMandatory();return mandatory != null ? mandatory : this.properties.isPublisherReturns();}private RetryTemplate createRetryTemplate(Retry properties) {RetryTemplate template = new RetryTemplate();SimpleRetryPolicy policy = new SimpleRetryPolicy();policy.setMaxAttempts(properties.getMaxAttempts());template.setRetryPolicy(policy);ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();backOffPolicy.setInitialInterval(properties.getInitialInterval());backOffPolicy.setMultiplier(properties.getMultiplier());backOffPolicy.setMaxInterval(properties.getMaxInterval());template.setBackOffPolicy(backOffPolicy);return template;}@Bean@ConditionalOnSingleCandidate(ConnectionFactory.class)@ConditionalOnProperty(prefix = "spring.rabbitmq",name = {"dynamic"},matchIfMissing = true)@ConditionalOnMissingBean({AmqpAdmin.class})public AmqpAdmin amqpAdmin(ConnectionFactory connectionFactory) {return new RabbitAdmin(connectionFactory);}}@Configuration@ConditionalOnMissingBean({ConnectionFactory.class})protected static class RabbitConnectionFactoryCreator {protected RabbitConnectionFactoryCreator() {}@Beanpublic CachingConnectionFactory rabbitConnectionFactory(RabbitProperties config) throws Exception {RabbitConnectionFactoryBean factory = new RabbitConnectionFactoryBean();if (config.determineHost() != null) {factory.setHost(config.determineHost());}factory.setPort(config.determinePort());if (config.determineUsername() != null) {factory.setUsername(config.determineUsername());}if (config.determinePassword() != null) {factory.setPassword(config.determinePassword());}if (config.determineVirtualHost() != null) {factory.setVirtualHost(config.determineVirtualHost());}if (config.getRequestedHeartbeat() != null) {factory.setRequestedHeartbeat(config.getRequestedHeartbeat());}Ssl ssl = config.getSsl();if (ssl.isEnabled()) {factory.setUseSSL(true);if (ssl.getAlgorithm() != null) {factory.setSslAlgorithm(ssl.getAlgorithm());}factory.setKeyStore(ssl.getKeyStore());factory.setKeyStorePassphrase(ssl.getKeyStorePassword());factory.setTrustStore(ssl.getTrustStore());factory.setTrustStorePassphrase(ssl.getTrustStorePassword());}if (config.getConnectionTimeout() != null) {factory.setConnectionTimeout(config.getConnectionTimeout());}factory.afterPropertiesSet();CachingConnectionFactory connectionFactory = new CachingConnectionFactory((com.rabbitmq.client.ConnectionFactory)factory.getObject());connectionFactory.setAddresses(config.determineAddresses());connectionFactory.setPublisherConfirms(config.isPublisherConfirms());connectionFactory.setPublisherReturns(config.isPublisherReturns());if (config.getCache().getChannel().getSize() != null) {connectionFactory.setChannelCacheSize(config.getCache().getChannel().getSize());}if (config.getCache().getConnection().getMode() != null) {connectionFactory.setCacheMode(config.getCache().getConnection().getMode());}if (config.getCache().getConnection().getSize() != null) {connectionFactory.setConnectionCacheSize(config.getCache().getConnection().getSize());}if (config.getCache().getChannel().getCheckoutTimeout() != null) {connectionFactory.setChannelCheckoutTimeout(config.getCache().getChannel().getCheckoutTimeout());}return connectionFactory;}}
}
相关文章:

Spring Boot 的自动配置,以rabbitmq为例,请详细说明
Spring Boot 的自动配置特性能够大大简化集成外部服务和组件的配置过程。以 RabbitMQ 为例,Spring Boot 通过 spring-boot-starter-amqp 提供了自动配置支持,开发者只需在应用中添加相关依赖并配置必要的属性,Spring Boot 会自动配置所需的连…...

Visual Studio 2022+Qt6.5.3安装教程+环境配置+创建Qt项目+乱码插件+运行很完美(16岁孩子也能看懂)
点击上方"蓝字"关注我们 01、安装VS2022 >>> 一、安装VS2022 1、VS2022下载链接:Visual Studio 2022 IDE - 适用于软件开发人员的编程工具[https://visualstudio.microsoft.com/zh-hans/vs/] 2、选择Community 2022个人免费版,点击下载[https://gitcode.…...

LeetCode - 初级算法 数组(旋转数组)
旋转数组 这篇文章讨论如何通过编程实现数组元素的旋转操作。 免责声明:本文来源于个人知识与公开资料,仅用于学术交流。 描述 给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。 示例: 输入: nums = [1,2,3,...

logback日志框架源码分析
目录 (一)入口:slf4j选择日志框架 (二)日志框架初始化 (1)logback的3种配置方式 a、BasicConfigurator默认配置 b、SPI方式配置的Configurator实现类 c、通过配置文件初始化 (2)xml配置文件初始化 (三)Logger的创建 (四)打印日志 本文源码基于:logback版…...

【微服务】3、配置管理
微服务配置管理 已掌握的微服务组件及配置管理问题引出 已掌握注册中心、Openfan、远程调用、负载均衡、网关等组件,具备微服务开发能力,但仍存在其他问题待解决。微服务和网关存在大量配置文件,其中包含很多重复配置,如数据库、日…...

数据分析思维(七):分析方法——群组分析方法
数据分析并非只是简单的数据分析工具三板斧——Excel、SQL、Python,更重要的是数据分析思维。没有数据分析思维和业务知识,就算拿到一堆数据,也不知道如何下手。 推荐书本《数据分析思维——分析方法和业务知识》,本文内容就是提取…...

概述(讲讲python基本语法和第三方库)
我是北子,这是我自己写的python教程,主要是记录自己的学习成果方便自己日后复习, 我先学了C/C,所以这套教程中可能会将很多概念和C/C去对比,所以该教程大概不适合零基础的人。 it seems that python nowadays 只在人工…...

力扣-20-有效的括号-栈
思路: 左括号每次匹配都是先匹配最后进来的,和栈的特点很相似,我们就可以利用栈来完成...

数据在内存中的存储【C语言版】
目录 1.举例: 2.深入刨析大端小端的组成: 3.判断当前编译环境是大端还是小端的方法 4.以函数的形式来判断当前的编译环境是大端还是小端【就是把判断大端小端的方法放进函数里面来实现,得到返回值,可以减少main()函数的内存】…...
【SQL】进阶知识 — 各大数据库合并几条数据到一行的方式
大家好,欢迎来到本期的 SQL 知识分享!今天我们要聊一个非常实用的技能:如何将多个行数据合并成一行!如果你曾经需要把多个查询结果合并成一个单元,或者把多行数据汇总到一个字段中,这篇文章将会教你如何用 …...

Gitee上传项目代码教程(详细)
工具必备:Git Bash 上传步骤 1.在Gitee创建项目仓库 2.进入本地项目目录 右键打开Git Bash here 3.配置用户名和邮箱 如果之前给git配置过用户名和邮箱可跳过 查看Git是否配置成功:git config --list git config --global user.name "xxx"…...

python ijson 用法教程
ijson PyPI Python ijson处理大型JSON文件 - 秀尊云 Python解析JSON大文件 | Leetaos Blog https://stackoverflow.com/questions/2400643/is-there-a-memory-efficient-and-fast-way-to-load-big-json-files/58148422#58148422 Python中读写(解析)J…...
什么是网络安全攻防演练,即红蓝对抗?
定义与目的 定义:网络安全攻防演练是一种模拟真实网络攻击和防御场景的活动,通过组织专业的攻击队伍(红队)和防御队伍(蓝队)进行对抗,来检验和提升组织的网络安全防御能力、应急响应能力和安全运…...

数据挖掘——决策树分类
数据挖掘——决策树分类 决策树分类Hunt算法信息增益增益比率基尼指数连续数据总结 决策树分类 树状结构,可以很好的对数据进行分类; 决策树的根节点到叶节点的每一条路径构建一条规则;具有互斥且完备的特点,即每一个样本均被且…...
Pytorch单、多GPU和CPU训练模型保存和加载
Pytorch多GPU训练模型保存和加载 在多GPU训练中,模型通常被包装在torch.nn.DataParallel或torch.nn.parallel.DistributedDataParallel中,这会在模型的参数名前加上module前缀。因此,在保存模型时,需要使用model.module.state_di…...
Karate 介绍与快速示例(API测试自动化、模拟、性能测试与UI自动化工具)
Karate是一个将API测试自动化、模拟、性能测试甚至UI自动化结合到一个统一框架中的开源工具。 Karate使用Gherkin 的BDD语法,是语言中性的,即使是非程序员也很容易。断言和HTML报告是内置的,支持并行运行测试以提高速度Karate 是用Java语言编写, 可以在Java 项目项目中运行…...
Pytest 高级用法:间接参数化
文章目录 1. 引言2. 基础概念2.1 Fixture2.2 参数化 3. 代码实例3.1 基础设置3.2 测试用例示例示例 1:基础的间接参数化示例 2:通过 request 获取参数值示例 3:多参数组合测试示例 4:部分间接参数化 4. 最佳实践5. 总结参考资料 1…...

第07章 存储管理(一)
一、磁盘简介 1.1 名称称呼 磁盘/硬盘/disk是同一个东西,不同于内存的是容量比较大。 1.2 类型 机械:机械硬盘即是传统普通硬盘,主要由:盘片,磁头,盘片转轴及控制电机,磁头控制器࿰…...
Go语言的 的设计模式(Design Patterns)核心知识
Go语言的设计模式(Design Patterns)核心知识 Go语言(Golang)是一种静态类型、编译型的编程语言,自2009年由Google正式推出以来,因其高效的性能、卓越的并发能力以及简洁的语法受到广泛欢迎。在软件开发中&…...

js函数预览图片:支持鼠标和手势拖拽缩放
对之前的方式改进:原生js实现图片预览控件,支持丝滑拖拽,滚轮放缩,放缩聚焦_js图片预览-CSDN博客 /*** 图片预览函数,调用后自动预览图片* param {图片地址} imgurl*/ function openImagePreview(imgurl) {if (!imgurl…...

基于FPGA的PID算法学习———实现PID比例控制算法
基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容:参考网站: PID算法控制 PID即:Proportional(比例)、Integral(积分&…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容
基于 UniApp + WebSocket实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

EtherNet/IP转DeviceNet协议网关详解
一,设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络,本网关连接到EtherNet/IP总线中做为从站使用,连接到DeviceNet总线中做为从站使用。 在自动…...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)
文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...

QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...

如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...
Java线上CPU飙高问题排查全指南
一、引言 在Java应用的线上运行环境中,CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时,通常会导致应用响应缓慢,甚至服务不可用,严重影响用户体验和业务运行。因此,掌握一套科学有效的CPU飙高问题排查方法&…...