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…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...
python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...
dedecms 织梦自定义表单留言增加ajax验证码功能
增加ajax功能模块,用户不点击提交按钮,只要输入框失去焦点,就会提前提示验证码是否正确。 一,模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...
页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...
laravel8+vue3.0+element-plus搭建方法
创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...
蓝桥杯 冶炼金属
原题目链接 🔧 冶炼金属转换率推测题解 📜 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V,是一个正整数,表示每 V V V 个普通金属 O O O 可以冶炼出 …...
GitFlow 工作模式(详解)
今天再学项目的过程中遇到使用gitflow模式管理代码,因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存,无论是github还是gittee,都是一种基于git去保存代码的形式,这样保存代码…...
Golang——7、包与接口详解
包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...
