zoukankan      html  css  js  c++  java
  • SpringCloud之Ribbon源码解析(三)--@LoadBalanced

    本文着重分析下为什么加了@LoadBalanced就有了负载均衡的能力

    先看现象

    我们写代码都是这么写的

    @SpringBootApplication
    @EnableEurekaClient
    @EnableDiscoveryClient
    public class ServiceRibbonApplication {
    
        public static void main(String[] args) {
            SpringApplication.run( ServiceRibbonApplication.class, args );
        }
    
        @Bean
        @LoadBalanced
        RestTemplate restTemplate() {
            return new RestTemplate();
        }

    如果不加@LoadBalanced会怎么样呢?

    @Configuration
    @ConditionalOnClass(RestTemplate.class)
    @ConditionalOnBean(LoadBalancerClient.class)
    @EnableConfigurationProperties(LoadBalancerRetryProperties.class)
    public class LoadBalancerAutoConfiguration {
    
        @LoadBalanced
        @Autowired(required = false)
        private List<RestTemplate> restTemplates = Collections.emptyList();
    
        @Bean
        public SmartInitializingSingleton loadBalancedRestTemplateInitializerDeprecated(
                final ObjectProvider<List<RestTemplateCustomizer>> restTemplateCustomizers) {
            return () -> restTemplateCustomizers.ifAvailable(customizers -> {
                for (RestTemplate restTemplate : LoadBalancerAutoConfiguration.this.restTemplates) {//如果不加LoadBalanced那么这里restTemplates就是size=0
                    for (RestTemplateCustomizer customizer : customizers) {
                        customizer.customize(restTemplate);
                    }
                }
            });
        }

    所以不加@LoadBalanced注解的话,在LoadBalancerAutoConfiguration就不能自动注入restTemplates,也就导致了没法讲interceptor注入到RestTemplate中,这样RestTemplate就不会有负载均衡的能力

    换句话说,如果不在启动类里面加 @LoadBalanced那么在LoadBalancerAutoConfiguration 中就没法完成@Autowired

    @Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @Qualifier
    public @interface LoadBalanced {
    }

    @LoadBalanced是@Qualifier的父类,所以它能配合@Autowired一起使用

    解析@Autowired最终会到达 DefaultListableBeanFactory

    protected boolean isAutowireCandidate(String beanName, RootBeanDefinition mbd,
    DependencyDescriptor descriptor, AutowireCandidateResolver resolver)
    protected boolean isAutowireCandidate(String beanName, RootBeanDefinition mbd,
                DependencyDescriptor descriptor, AutowireCandidateResolver resolver) {
    
            String beanDefinitionName = BeanFactoryUtils.transformedBeanName(beanName);
            resolveBeanClass(mbd, beanDefinitionName);
            if (mbd.isFactoryMethodUnique) {
                boolean resolve;
                synchronized (mbd.constructorArgumentLock) {
                    resolve = (mbd.resolvedConstructorOrFactoryMethod == null);
                }
                if (resolve) {
                    new ConstructorResolver(this).resolveFactoryMethodIfPossible(mbd);
                }
            }
            return resolver.isAutowireCandidate(
                    new BeanDefinitionHolder(mbd, beanName, getAliases(beanDefinitionName)), descriptor);
        }

    说下上面的参数

     1 beanName是要判断是否应该注入的beanName,比如restTemplate

     2 DependencyDescriptor是指 描述成员变量restTemplates 的注解信息的比如它有@LoadBalanced

    public class LoadBalancerAutoConfiguration {
    
        @LoadBalanced
        @Autowired(required = false)
        private List<RestTemplate> restTemplates = Collections.emptyList();

      QualifierAnnotationAutowireCandidateResolver

    public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) {
            boolean match = super.isAutowireCandidate(bdHolder, descriptor);
            if (match) {
                match = checkQualifiers(bdHolder, descriptor.getAnnotations());
                if (match) {
                    MethodParameter methodParam = descriptor.getMethodParameter();
                    if (methodParam != null) {
                        Method method = methodParam.getMethod();
                        if (method == null || void.class == method.getReturnType()) {
                            match = checkQualifiers(bdHolder, methodParam.getMethodAnnotations());
                        }
                    }
                }
            }
            return match;
        }
    protected boolean checkQualifiers(BeanDefinitionHolder bdHolder, Annotation[] annotationsToSearch) {
            if (ObjectUtils.isEmpty(annotationsToSearch)) {
                return true;
            }
            SimpleTypeConverter typeConverter = new SimpleTypeConverter();
            for (Annotation annotation : annotationsToSearch) {
                Class<? extends Annotation> type = annotation.annotationType();
                boolean checkMeta = true;
                boolean fallbackToMeta = false;
                if (isQualifier(type)) {
                    if (!checkQualifier(bdHolder, annotation, typeConverter)) {
                        fallbackToMeta = true;
                    }
                    else {
                        checkMeta = false;
                    }
                }
                if (checkMeta) {
                    boolean foundMeta = false;
                    for (Annotation metaAnn : type.getAnnotations()) {
                        Class<? extends Annotation> metaType = metaAnn.annotationType();
                        if (isQualifier(metaType)) {
                            foundMeta = true;
                            // Only accept fallback match if @Qualifier annotation has a value...
                            // Otherwise it is just a marker for a custom qualifier annotation.
                            if ((fallbackToMeta && StringUtils.isEmpty(AnnotationUtils.getValue(metaAnn))) ||
                                    !checkQualifier(bdHolder, metaAnn, typeConverter)) {
                                return false;
                            }
                        }
                    }
                    if (fallbackToMeta && !foundMeta) {
                        return false;
                    }
                }
            }
            return true;
        }

    就是判断DependencyDescriptor中有的注解,候选beanDefinition是否也有,如果没有那就不应该选择它作为@Autowired的候选了

    所以说知道当我们给RestTemplate加上@LoadBalanced注解它才有负载均衡的能力

  • 相关阅读:
    js基础整理总结
    pyinstaller打包django项目成exe以及遇到的一些问题
    Django对接SQL Server服务
    死锁
    python 之路
    Python注释
    Django2.1迁移数据库出错
    一行 Python 代码实现并行
    【转载】Python 类定义与对象
    关于盒模型布局在UC上的兼容处理
  • 原文地址:https://www.cnblogs.com/juniorMa/p/14421412.html
Copyright © 2011-2022 走看看