本文着重分析下为什么加了@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注解它才有负载均衡的能力