同一个工程配置多个mq及相关@ConditionalOnSingleCandidate、@Autowired和@Resource

@ConditionalOnSingleCandidate表示当指定Bean在容器中只有一个,或者虽然有多个但是指定首选Bean。
同一个工程里配置不同的mq,并且不同位置各自使用。
重写 RabbitAutoConfiguration这个类里实例化的bean, RabbitTemplateConfiguration下的 RabbitTemplateAmqpAdmin以及 RabbitMessagingTemplate
使用的时候注入不同类名的,以及注解里指定各自name的。
要注入相同类型不同名字的,此时便用到了@Resource,按默认name和自定义的name分别注入。
 
========================回顾一下@Autowired和@Resource的知识===========
@Autowired注解是按类型装配依赖对象,默认情况下它要求依赖对象必须存在,如果允许null,可以设置它required属性为false。
@Resource注解和@Autowired一样,也可以标注在字段或属性的setter方法上,但它默认按名称装配。名称可以通过@Resource的name属性指定,如果没有指定name属性,当注解标注在字段上,即默认取字段的名称作为bean名称寻找依赖对象,当注解标注在属性的setter方法上,即默认取属性名作为bean名称寻找依赖对象。
@Resources按名字,是jdk的,@Autowired按类型,是spring的。
处理这2个注解的BeanPostProcessor不一样
CommonAnnotationBeanPostProcessor是处理@ReSource注解的
AutoWiredAnnotationBeanPostProcessor是处理@AutoWired注解的
@Autowired只按照byType 注入;@Resource默认按byName自动注入,也提供按照byType 注入;
@Resource如果没有指定name属性,并且按照默认的名称仍然找不到依赖对象时, @Resource注解会回退到按类型装配。但一旦指定了name属性,就只能按名称装配了。

@Resource装配顺序
  1. 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常
  2. 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常
  3. 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常
  4. 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;
==========================
 
 
/*
* Copyright 2012-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
 
 
package org.springframework.boot.autoconfigure.amqp;
 
 
import java.time.Duration;
import java.util.Objects;
 
 
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.ConnectionNameStrategy;
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.EnableAutoConfiguration;
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.boot.context.properties.PropertyMapper;
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;
import org.springframework.util.ReflectionUtils;
 
 
/**
* {@link EnableAutoConfiguration Auto-configuration} for {@link RabbitTemplate}.
* <p>
* This configuration class is active only when the RabbitMQ and Spring AMQP client
* libraries are on the classpath.
* <P>
* Registers the following beans:
* <ul>
* <li>{@link org.springframework.amqp.rabbit.core.RabbitTemplate RabbitTemplate} if there
* is no other bean of the same type in the context.</li>
* <li>{@link org.springframework.amqp.rabbit.connection.CachingConnectionFactory
* CachingConnectionFactory} instance if there is no other bean of the same type in the
* context.</li>
* <li>{@link org.springframework.amqp.core.AmqpAdmin } instance as long as
* {@literal spring.rabbitmq.dynamic=true}.</li>
* </ul>
* <p>
* The {@link org.springframework.amqp.rabbit.connection.CachingConnectionFactory} honors
* the following properties:
* <ul>
* <li>{@literal spring.rabbitmq.port} is used to specify the port to which the client
* should connect, and defaults to 5672.</li>
* <li>{@literal spring.rabbitmq.username} is used to specify the (optional) username.
* </li>
* <li>{@literal spring.rabbitmq.password} is used to specify the (optional) password.
* </li>
* <li>{@literal spring.rabbitmq.host} is used to specify the host, and defaults to
* {@literal localhost}.</li>
* <li>{@literal spring.rabbitmq.virtualHost} is used to specify the (optional) virtual
* host to which the client should connect.</li>
* </ul>
*
* @author Greg Turnquist
* @author Josh Long
* @author Stephane Nicoll
* @author Gary Russell
* @author Phillip Webb
*/
@Configuration
@ConditionalOnClass({ RabbitTemplate.class, Channel.class })
@EnableConfigurationProperties(RabbitProperties.class)
@Import(RabbitAnnotationDrivenConfiguration.class)
public class RabbitAutoConfiguration {
 
 
   @Configuration
   @ConditionalOnMissingBean(ConnectionFactory.class)
   protected static class RabbitConnectionFactoryCreator {
 
 
      // Only available in rabbitmq-java-client 5.4.0 +
      private static final boolean CAN_ENABLE_HOSTNAME_VERIFICATION = ReflectionUtils
            .findMethod(com.rabbitmq.client.ConnectionFactory.class,
                  "enableHostnameVerification") != null;
 
 
      @Bean
      public CachingConnectionFactory rabbitConnectionFactory(
            RabbitProperties properties,
            ObjectProvider<ConnectionNameStrategy> connectionNameStrategy)
            throws Exception {
         PropertyMapper map = PropertyMapper.get();
         CachingConnectionFactory factory = new CachingConnectionFactory(
               getRabbitConnectionFactoryBean(properties).getObject());
         map.from(properties::determineAddresses).to(factory::setAddresses);
         map.from(properties::isPublisherConfirms).to(factory::setPublisherConfirms);
         map.from(properties::isPublisherReturns).to(factory::setPublisherReturns);
         RabbitProperties.Cache.Channel channel = properties.getCache().getChannel();
         map.from(channel::getSize).whenNonNull().to(factory::setChannelCacheSize);
         map.from(channel::getCheckoutTimeout).whenNonNull().as(Duration::toMillis)
               .to(factory::setChannelCheckoutTimeout);
         RabbitProperties.Cache.Connection connection = properties.getCache()
               .getConnection();
         map.from(connection::getMode).whenNonNull().to(factory::setCacheMode);
         map.from(connection::getSize).whenNonNull()
               .to(factory::setConnectionCacheSize);
         map.from(connectionNameStrategy::getIfUnique).whenNonNull()
               .to(factory::setConnectionNameStrategy);
         return factory;
      }
 
 
      private RabbitConnectionFactoryBean getRabbitConnectionFactoryBean(
            RabbitProperties properties) throws Exception {
         PropertyMapper map = PropertyMapper.get();
         RabbitConnectionFactoryBean factory = new RabbitConnectionFactoryBean();
         map.from(properties::determineHost).whenNonNull().to(factory::setHost);
         map.from(properties::determinePort).to(factory::setPort);
         map.from(properties::determineUsername).whenNonNull()
               .to(factory::setUsername);
         map.from(properties::determinePassword).whenNonNull()
               .to(factory::setPassword);
         map.from(properties::determineVirtualHost).whenNonNull()
               .to(factory::setVirtualHost);
         map.from(properties::getRequestedHeartbeat).whenNonNull()
               .asInt(Duration::getSeconds).to(factory::setRequestedHeartbeat);
         RabbitProperties.Ssl ssl = properties.getSsl();
         if (ssl.isEnabled()) {
            factory.setUseSSL(true);
            map.from(ssl::getAlgorithm).whenNonNull().to(factory::setSslAlgorithm);
            map.from(ssl::getKeyStoreType).to(factory::setKeyStoreType);
            map.from(ssl::getKeyStore).to(factory::setKeyStore);
            map.from(ssl::getKeyStorePassword).to(factory::setKeyStorePassphrase);
            map.from(ssl::getTrustStoreType).to(factory::setTrustStoreType);
            map.from(ssl::getTrustStore).to(factory::setTrustStore);
            map.from(ssl::getTrustStorePassword).to(factory::setTrustStorePassphrase);
            map.from(ssl::isValidateServerCertificate).to((validate) -> factory
                  .setSkipServerCertificateValidation(!validate));
            map.from(ssl::getVerifyHostname).when(Objects::nonNull)
                  .to(factory::setEnableHostnameVerification);
            if (ssl.getVerifyHostname() == null && CAN_ENABLE_HOSTNAME_VERIFICATION) {
               factory.setEnableHostnameVerification(true);
            }
         }
         map.from(properties::getConnectionTimeout).whenNonNull()
               .asInt(Duration::toMillis).to(factory::setConnectionTimeout);
         factory.afterPropertiesSet();
         return factory;
      }
 
 
   }
 
 
   @Configuration
   @Import(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
      public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
         PropertyMapper map = PropertyMapper.get();
         RabbitTemplate template = new RabbitTemplate(connectionFactory);
         MessageConverter messageConverter = this.messageConverter.getIfUnique();
         if (messageConverter != null) {
            template.setMessageConverter(messageConverter);
         }
         template.setMandatory(determineMandatoryFlag());
         RabbitProperties.Template properties = this.properties.getTemplate();
         if (properties.getRetry().isEnabled()) {
            template.setRetryTemplate(createRetryTemplate(properties.getRetry()));
         }
         map.from(properties::getReceiveTimeout).whenNonNull().as(Duration::toMillis)
               .to(template::setReceiveTimeout);
         map.from(properties::getReplyTimeout).whenNonNull().as(Duration::toMillis)
               .to(template::setReplyTimeout);
         map.from(properties::getExchange).to(template::setExchange);
         map.from(properties::getRoutingKey).to(template::setRoutingKey);
         return template;
      }
 
 
      private boolean determineMandatoryFlag() {
         Boolean mandatory = this.properties.getTemplate().getMandatory();
         return (mandatory != null) ? mandatory : this.properties.isPublisherReturns();
      }
 
 
      private RetryTemplate createRetryTemplate(RabbitProperties.Retry properties) {
         PropertyMapper map = PropertyMapper.get();
         RetryTemplate template = new RetryTemplate();
         SimpleRetryPolicy policy = new SimpleRetryPolicy();
         map.from(properties::getMaxAttempts).to(policy::setMaxAttempts);
         template.setRetryPolicy(policy);
         ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
         map.from(properties::getInitialInterval).whenNonNull().as(Duration::toMillis)
               .to(backOffPolicy::setInitialInterval);
         map.from(properties::getMultiplier).to(backOffPolicy::setMultiplier);
         map.from(properties::getMaxInterval).whenNonNull().as(Duration::toMillis)
               .to(backOffPolicy::setMaxInterval);
         template.setBackOffPolicy(backOffPolicy);
         return template;
      }
 
 
      @Bean
      @ConditionalOnSingleCandidate(ConnectionFactory.class)
      @ConditionalOnProperty(prefix = "spring.rabbitmq", name = "dynamic", matchIfMissing = true)
      @ConditionalOnMissingBean
      public AmqpAdmin amqpAdmin(ConnectionFactory connectionFactory) {
         return new RabbitAdmin(connectionFactory);
      }
 
 
   }
 
 
   @Configuration
   @ConditionalOnClass(RabbitMessagingTemplate.class)
   @ConditionalOnMissingBean(RabbitMessagingTemplate.class)
   @Import(RabbitTemplateConfiguration.class)
   protected static class MessagingTemplateConfiguration {
 
 
      @Bean
      @ConditionalOnSingleCandidate(RabbitTemplate.class)
      public RabbitMessagingTemplate rabbitMessagingTemplate(
            RabbitTemplate rabbitTemplate) {
         return new RabbitMessagingTemplate(rabbitTemplate);
      }
 
 
   }
 
 
}
 
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值