做网站页面多少钱,外包seo公司,网站建设模板制作,节能网站源码Spring Boot 的自动配置特性能够大大简化集成外部服务和组件的配置过程。以 RabbitMQ 为例#xff0c;Spring Boot 通过 spring-boot-starter-amqp 提供了自动配置支持#xff0c;开发者只需在应用中添加相关依赖并配置必要的属性#xff0c;Spring Boot 会自动配置所需的连…Spring Boot 的自动配置特性能够大大简化集成外部服务和组件的配置过程。以 RabbitMQ 为例Spring Boot 通过 spring-boot-starter-amqp 提供了自动配置支持开发者只需在应用中添加相关依赖并配置必要的属性Spring Boot 会自动配置所需的连接工厂、消息队列、交换机、消息模板等。
以下是以 RabbitMQ 为例的详细说明。
1. 引入 RabbitMQ 依赖
要使用 Spring Boot 集成 RabbitMQ首先需要在项目的 pom.xml 文件中添加 spring-boot-starter-amqp 依赖这个依赖包含了与 RabbitMQ 交互的所有必要组件。
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-amqp/artifactId
/dependencyspring-boot-starter-amqp 依赖包含了 Spring AMQP 和 RabbitMQ 的连接组件自动配置会根据此依赖自动启用 RabbitMQ 相关功能。
2. 配置 RabbitMQ 连接属性
接下来你需要在 application.properties 或 application.yml 中配置 RabbitMQ 的连接信息。例如
使用 application.properties
spring.rabbitmq.hostlocalhost
spring.rabbitmq.port5672
spring.rabbitmq.usernameguest
spring.rabbitmq.passwordguest
spring.rabbitmq.virtual-host/
spring.rabbitmq.publisher-confirm-typesimple
spring.rabbitmq.listener.simple.concurrency3
spring.rabbitmq.listener.simple.max-concurrency10spring.rabbitmq.hostRabbitMQ 服务器的地址通常是 localhost。spring.rabbitmq.portRabbitMQ 服务器的端口默认是 5672。spring.rabbitmq.username 和 spring.rabbitmq.passwordRabbitMQ 的认证信息。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 的 BeanSpring 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.concurrency5
spring.rabbitmq.listener.simple.max-concurrency10这将允许 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 依赖中看到这一点
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-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;}BeanConditionalOnMissingBean(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;}BeanConditionalOnMissingBean(RabbitTemplate.class)public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {RabbitTemplate rabbitTemplate new RabbitTemplate(connectionFactory);rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());return rabbitTemplate;}BeanConditionalOnMissingBean(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 类型的 BeanSpring 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. 总结
通过 RabbitAutoConfigurationSpring 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() {}ConfigurationConditionalOnClass({RabbitMessagingTemplate.class})ConditionalOnMissingBean({RabbitMessagingTemplate.class})Import({RabbitAutoConfiguration.RabbitTemplateConfiguration.class})protected static class MessagingTemplateConfiguration {protected MessagingTemplateConfiguration() {}BeanConditionalOnSingleCandidate(RabbitTemplate.class)public RabbitMessagingTemplate rabbitMessagingTemplate(RabbitTemplate rabbitTemplate) {return new RabbitMessagingTemplate(rabbitTemplate);}}ConfigurationImport({RabbitAutoConfiguration.RabbitConnectionFactoryCreator.class})protected static class RabbitTemplateConfiguration {private final ObjectProviderMessageConverter messageConverter;private final RabbitProperties properties;public RabbitTemplateConfiguration(ObjectProviderMessageConverter messageConverter, RabbitProperties properties) {this.messageConverter messageConverter;this.properties properties;}BeanConditionalOnSingleCandidate(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;}BeanConditionalOnSingleCandidate(ConnectionFactory.class)ConditionalOnProperty(prefix spring.rabbitmq,name {dynamic},matchIfMissing true)ConditionalOnMissingBean({AmqpAdmin.class})public AmqpAdmin amqpAdmin(ConnectionFactory connectionFactory) {return new RabbitAdmin(connectionFactory);}}ConfigurationConditionalOnMissingBean({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;}}
}