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 会自动配置所需的连…...
ros2-4.1 服务通信介绍
服务是ROS图中节点之间的另一种通信方法。服务分为客户端和服务端,客户端发送请求给服务端,服务端可以根据客户端的请求做一些处理,然后返回结果给客户端。也称为为请求-响应模型。 服务和话题的不同之处,话题是没有返回的&#…...
如何 cURL Elasticsearch:进入 Shell
作者:来自 Elastic Philipp Krenn Kibana 的控制台是开始使用 Elasticsearch 的 REST API 的最简单方法 - 语法突出显示、自动完成、格式化、导出 cURL、JavaScript 或 Python。而且你不必担心正确的端点、身份验证等。但是有时,如果 Kibana 不可用、你…...
【信息系统项目管理师】高分论文:论信息系统项目的风险管理(人民医院的信息系统)
更多内容请见: 备考信息系统项目管理师-专栏介绍和目录 文章目录 论文1、规划风险管理2、项目风险识别3、风险定性分析4、风险定量分析5、制定风险应对6、实施风险应对计划7、监督风险论文 2022年6月,我作为项目经理承担了XX县人民医院的信息系统建设,该项目总投资300万,其…...
安装和配置 Apache 及 PHP
安装和配置 Apache 及 PHP # 1. 停止当前 Apache 服务 sudo apachectl stop# 2. 清除现有的 Apache 配置和文件 sudo rm -rf /etc/apache2 sudo rm -rf /usr/sbin/httpd sudo rm -rf /Library/WebServer# 3. 使用 Homebrew 安装 Apache brew install httpd# 4. 启动 Apache su…...
jenkins入门12-- 权限管理
Jenkins的权限管理 由于jenkins默认的权限管理体系不支持用户组或角色的配置,因此需要安装第三发插件来支持角色的配置,我们使用Role-based Authorization Strategy 插件 只有项目读权限 只有某个项目执行权限...
虚功、达朗贝尔原理和拉格朗日方程
本文先引入虚位移,从虚功和虚功原理出发,介绍达朗贝尔原理(d’Alembert’s principle) 和 拉格朗日方程(Lagrange’s equations)。 1. 虚功 力学系统的虚位移(virtual displacement)或称无限小位移(infinitesimal displacement)是指力学系统的位形(configuration …...
面向对象分析和设计OOA/D,UML,GRASP
目录 什么是分析和设计? 什么是面向对象的分析和设计? 迭代开发 UML 用例图 交互图 基于职责驱动设计 GRASP 常见设计原则 什么是分析和设计? 分析,强调是对问题和需求的调查研究,不是解决方案。例如&#x…...
【Linux】记录一下考RHCE的学习过程(七)
年底了,公司接的北京地铁轨道交通的项目做不完了,一百多列地铁的设备都得调,派我出差了几周,这几天才回来,出差累死了实在是没办法更新。(YOASOBI的二开票还没抢到ToT,哭死,看看回滚…...
【深度学习】深度(Deep Learning)学习基础
深度学习(Deep Learning) 深度学习是一种基于人工神经网络的机器学习方法,通过多个层次(深度)的神经网络从数据中自动学习特征和模式。它是人工智能的一个核心领域,尤其在处理复杂数据(如图像、…...
121 买入股票的最佳时机
思路1: 买的那天一定是卖的那天之前的最小值。 每到一天,维护那天之前的最小值即可。 假设第一天是最小值,最大值初始化为0,当以后某天的价格小于最小值时,将最小值更新 当天价格大于最小值,说明有利可图…...
JVM之Java内存模型
Java内存模型(Java Memory Model,简称JMM)是Java虚拟机(JVM)规范中定义的一套规则,用于描述多线程环境下变量如何被访问和同步。在多线程编程中,内存模型的重要性不言而喻,它直接关系…...
matlab系列专栏-快捷键速查手册
目录 1在命令窗口(Command Window)中 2. 在编辑器(Editor)(m文件)中 1在命令窗口(Command Window)中 1)【↑、↓】——切换到之前、之后运行过的命令,可以重复按多次来达到想要的命令。 2)【Tab】——自动补全。在Command窗口,…...
快手一面-面经
1. RPC和Http的区别? RPC(Remote Procedure Call,远程过程调用)和 HTTP(HyperText Transfer Protocol,超文本传输协议)是两种不同的通信机制,它们有不同的用途、工作原理和应用场景…...
<style lang=“scss“ scoped>: 这是更常见的写法,也是官方文档中推荐的写法
这两种写法在大多数情况下是没有区别的,它们都是 Vue.js 单文件组件 (.vue 文件) 中用来定义组件私有样式的方式。 两种写法: <style lang"scss" scoped>: 这是更常见的写法,也是官方文档中推荐的写法。<style scoped l…...
cerebro关闭ssl
cerebro连接es报错 io.netty.handler.codec.DecoderException: javax.net.ssl.SSLHandshakeException: (certificate_unknown) Received fatal alert: certificate_unknown 在cerebro的application.conf配置文件中添加 play.ws.ssl.loose.acceptAnyCertificate true Disab…...
网络安全常见的问题
1. 什么是 DDoS 攻击?如何防范? 答:DDoS 攻击是指利用大量的计算机或者其他网络设备,同时向目标网络或者服务器 发送 大量的数据流量,以致其无法正常工作,从而导致网络瘫痪或者服务器宕机的攻击行 为。 …...
Eclipse配置Tomcat服务器(最全图文详解)
前言: 本章使用图文讲解如何在Eclipse开发工具中配置Tomcat服务器、如何创建和启动JavaWeb工程,欢迎童鞋们互相交流。觉得不错可以三连订阅喔。 目标: 一、配置Tomcat服务器 1. 切换Eclipse视图 2. 打开菜单 3. 找到服务选项 4. 选择…...
mv指令详解
🏝️专栏:https://blog.csdn.net/2301_81831423/category_12872319.html 🌅主页:猫咪-9527-CSDN博客 “欲穷千里目,更上一层楼。会当凌绝顶,一览众山小。” 目录 基本语法 主要功能 常用选项详解 1. …...
SQL从入门到实战
学前须知 sqlzoo数据介绍 world nobel covid ge game、goal、eteam teacher、dept movie、casting、actor 基础语句 select&from SELECT from WORLD Tutorial - SQLZoo 基础查询select单列&多列&所有列&别名应用 例题一 SELECT name, continent, population …...
回归中医传统 重铸中医之魂 — 薛应中 —
最近做了一个20次课的讲义纲要,每节课都是中医理念下某一类疾病的认知与诊疗,或是一个重大健康观念的辨析,准备陆续和各届人士一起探讨。 下面就算是一个序言,主要是做一个自我介绍,将自己的一点心得,结合我的行医经历,以及学习中医的治学之道等,做一个开场白。 (一)中医的有…...
什么是面向对象?
面向对象编程(Object-Oriented Programming,简称OOP)是一种流行的编程方法,它以对象和类为基础构建软件。该编程范式围绕“对象”这一基本概念展开,其中对象被视为包含数据和行为的软件构件。以下是对面向对象编程的深…...
HDFS读写流程
因为namenode维护管理了文件系统的元数据信息,这就造成了不管是读还是写数据都是基于NameNode开始的,也就是说NameNode成为了HDFS访问的唯一入口。入口地址是:http://nn_host:8020。 一、写数据流程 1.1 Pipeline管道、ACK应答响应 Pipeline…...
HDFS Federation联邦机制
一、当前HDFS体系架构 1.1 简介 当前的HDFS架构有两个主要的层: 命名空间(namespace) HDFS体系结构中的命名空间层由文件,块和目录组成。该层支持与名称空间相关的文件系统操作,例如创建,删除࿰…...
机器学习周报-ModernTCN文献阅读
文章目录 摘要Abstract 0 提升有效感受野(ERF)1 相关知识1.1 标准卷积1.2 深度分离卷积(Depthwise Convolution,DWConv)1.3 逐点卷积(Pointwise Convolution,PWConv)1.4 组卷积(Grou…...
QT RC_FILE 应用程序图标设置
1.先做一个app.ico 文件,并将文件放入资源文件夹中 2.打开QT项目的.pro文件在最下面增加 RC_FILE $$PWD/res/app.rc 3.在资源文件夹中创建一个app.rc文件。在QT开发工具中编辑并输入下在内容 IDI_ICON1 ICON "app.ico" 4.测试效果...
5G学习笔记之SNPN系列之网络选择
目录 0. NPN系列 1. 概述 2. 自动网络选择 3. 手动网络选择 0. NPN系列 1. NPN概述 2. NPN R18 3. 【SNPN系列】SNPN ID和广播消息 4. 【SNPN系列】UE入网和远程配置 5. 【SNPN系列】SNPN选择 6. PNI-NPN 1. 概述 对于某个特定的UE,可以仅支持SNPN接入模式&#x…...
k8s helm部署kafka集群(KRaft模式)——筑梦之路
添加helm仓库 helm repo add bitnami "https://helm-charts.itboon.top/bitnami" --force-update helm repo add grafana "https://helm-charts.itboon.top/grafana" --force-update helm repo add prometheus-community "https://helm-charts.itboo…...
Redis学习笔记
目录 Nosql概述 为什么用Nosql 什么是Nosql Nosql四大分类 Redis入门 概述 Windows安装 Linux安装 测试性能 基础知识 五大数据类型 Redis-Key String(字符串) List(列表) Set(集合) Hash(哈希) Zset(有…...
mysql递归查询语法WITH RECURSIVE
WITH RECURSIVE 是 SQL 中用于执行递归查询的语法,特别适合于处理层级结构或递归数据(如树形结构、图结构)。递归查询可以反复引用自己来查询多层次的数据,而无需写多个嵌套查询。 基本语法结构: WITH RECURSIVE CTE…...
Go语言之十条命令(The Ten Commands of Go Language)
Go语言之十条命令 Go语言简介 Go语言(又称Golang)是由Google开发的一种开源编程语言,首次公开发布于2009年。Go语言旨在提供简洁、高效、可靠的软件开发解决方案,特别强调并发编程和系统编程。 Go语言的基本特征 静态强类…...
Visual Studio 2022 C++ gRPC 环境搭建
文章目录 1、gRPC 安装2、创建项目2.1、创建 “空的解决方案”2.2、新建 gRPCServer 和 gRPCClient 项目2.3、创建 proto 文件 2、为 gRPC 服务端和客服端项目配置 protobuf 编译2.1、protobuf 配置2.2、gRPCServer 项目配置2.3、gRPCClient 项目配置 3、测试3.1、启动服务端程…...
2024AAAI SCTNet论文阅读笔记
文章目录 SCTNet: Single-Branch CNN with Transformer Semantic Information for Real-Time Segmentation摘要背景创新点方法Conv-Former Block卷积注意力机制前馈网络FFN 语义信息对齐模块主干特征对齐共享解码头对齐 总体架构backbone解码器头 对齐损失 实验SOTA效果对比Cit…...
【Java从入门到放弃 之 final 关键字】
final 关键字 final 关键字final 字段final 函数列表中的参数final 方法final 类 final 关键字 Java中里面有final这个关键字,这个关键字总体上是用来表达” 不能被改变“ 这个意思的。我们使用这个关键字表达不能被改变,有两种使用场景,有三…...
【U8+】用友U8软件中,出入库流水输出excel的时候提示报表输出引擎错误。
【问题现象】 通过天联高级版客户端登录拥有U8后, 将出入库流水输出excel的时候,提示报表输出引擎错误。 进行报表输出时出现错误,错误信息:找不到“fd6eea8b-fb40-4ce4-8ab4-cddbd9462981.htm”。 如果您正试图从最近使用的文件列…...
文本区域提取和分析——Python版本
目录 1. 图像预处理 2. 文本区域提取 3. 文本行分割 4. 文本区域分析 5. 应用举例 总结 文本区域提取和分析是计算机视觉中的重要任务,尤其在光学字符识别(OCR)系统、文档分析、自动化数据录入等应用中有广泛的应用。其目标是从图像中提…...
数据库介绍(不同数据库比较)
文章目录 **一、关系型数据库(RDBMS)****1. MySQL****优点**:**缺点**:**适用场景**: **2. PostgreSQL****优点**:**缺点**:**适用场景**: **3. Oracle Database****优点**ÿ…...
注意力的简单理解,有哪些注意力(Attention)
注意力(Attention) 目录 注意力(Attention)掩码注意力机制自注意力、交叉注意力、掩码注意力的不同点适应场景及举例多头注意分层注意力(Hierarchical Attention)协同注意力(Co - Attention)自注意力(Self - Attention) 简单理解:自注意力就像是一个句子(或序列)内…...
基于Python的投资组合收益率与波动率的数据分析
基于Python的投资组合收益率与波动率的数据分析 摘要:該文通过研究马科维茨的投资组合模型,并将投资组合模型应用到包含6只金融股票的金融行业基金中。首先通过开源的财经接口Tushare获取股票原始数据,接着利用数据分析的黄金组合库…...
《Opencv》图像的旋转
一、使用numpy库实现 np.rot90(img,-1) 后面的参数为-1时事顺时针旋转,为1时是逆时针旋转。 import cv2 import numpy as np img cv2.imread(./images/kele.png) """方法一""" # 顺时针90度 rot_1 np.rot90(img,-1) # 逆时针90度…...
Python 22:注释
1. 定义: 用熟悉的语言对代码进行解释说明。注释不会被执行。 2. 注释分类 单行注释:只能对一行代码进行注释。放在要注释的代码后面,用#进行分隔,中间至少空2个空格,保证代码规范。 print("hello world10"…...
python:利用神经网络技术确定大量离散点中纵坐标可信度的最高集中区间
当我们有许多离散点并想要确定纵坐标在某个区间内的可信度时,我们可以使用神经网络模型来解决这个问题。下面是一个使用Python编写的示例代码,展示了如何使用神经网络来确定大量离散点中纵坐标可信度的最高集中区间。 import numpy as np from sklearn.…...
计算机软件保护条例
(2001年12月20日中华人民共和国国务院令第339号公布 根据2011年1月8日《国务院关于废止和修改部分行政法规的决定》第一次修订 根据2013年1月30日《国务院关于修改〈计算机软件保护条例〉的决定》第二次修订) 第一章 总则 第一条 为了保护计算机软件著作权人的权益&#…...
CM3/4启动流程
CM3/4启动流程 1. 启动模式2. 启动流程 1. 启动模式 复位方式有三种:上电复位,硬件复位和软件复位。 当产生复位,并且离开复位状态后,CM3/4 内核做的第一件事就是读取下列两个 32 位整数的值: 从地址 0x0000 0000 处取…...
gaussdb中怎么查询一个表有多少GB
在 GaussDB 中,你可以通过多种方法查询一个表的大小,包括使用系统视图和内置函数。以下是几种常见的方法: 1. 使用 pg_total_relation_size 函数 pg_total_relation_size 函数返回一个表及其所有索引和 TOAST 数据的总大小。 示例查询 SE…...
2025-01-06 Unity 使用 Tip2 —— Windows、Android、WebGL 打包记录
文章目录 1 Windows2 Android2.1 横版 / 竖版游戏2.2 API 最低版本2.3 目标帧率2.3.1 targetFrameRate2.3.2 vSyncCount2.3.3 Unity 默认设置以及推荐设置2.3.4 Unity 帧率托管 3 WebGL3.1 平台限制3.2 打包报错记录 13.3 打包报错记录 2 最近尝试将写的小游戏打包ÿ…...
OP-TEE环境飞腾密码引擎编程指南
【写在前面】 飞腾开发者平台是基于飞腾自身强大的技术基础和开放能力,聚合行业内优秀资源而打造的。该平台覆盖了操作系统、算法、数据库、安全、平台工具、虚拟化、存储、网络、固件等多个前沿技术领域,包含了应用使能套件、软件仓库、软件支持、软件适…...
解密Navicat密码(Java)
最近从Navicat换到了DBeaver,导出配置文件发现配置文件里的密码都是加密的,看网上的都是给的PHP代码,因为环境问题,就算是在线上运行的PHP代码也会报错,所以就把这段代码改成Java了。 package com.unicdata.system.con…...
apex安装
安装过程复杂曲折,网上说的很多办法,貌似成功了,实际还是没起作用。 先说成功过程,执行下面命令,安装成功(当然,前提是你要先配置好编译环境): (我的环境&a…...
常见的开源网络操作系统
常见的开源网络操作系统有很多,它们通常用于路由器、交换机、网络设备和服务器等场景,具有灵活、可定制、易于扩展的特点。以下是一些常见的开源网络操作系统: OpenWRT 用途:主要用于路由器、无线接入点和网络设备。提供了广泛的定制选项和高级功能,如防火墙配置、VPN 支持…...