@LoadBalanced注解原理
在使用springcloud ribbon客户端负载均衡的时候,可以给RestTemplate bean 加一个@LoadBalanced注解,就能让这个RestTemplate在请求时拥有客户端负载均衡的能力:
@Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
- 1
- 2
- 3
- 4
- 5
是不是很神奇?打开@LoadBalanced的注解源码,并没有什么特殊的东东
package org.springframework.cloud.client.loadbalancer;
import org.springframework.beans.factory.annotation.Qualifier;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
- Annotation to mark a RestTemplate bean to be configured to use a LoadBalancerClient
- @author Spencer Gibb
*/
@Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Qualifier
public @interface LoadBalanced {
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
唯一不同的地方就是多了一个@Qulifier注解.
搜索@LoadBalanced注解的使用地方,发现只有一处使用了,在LoadBalancerAutoConfiguration这个自动装配类中:
@LoadBalanced
@Autowired(required = false)
private List<RestTemplate> restTemplates = Collections.emptyList();
@Bean
public SmartInitializingSingleton loadBalancedRestTemplateInitializer(
final List<RestTemplateCustomizer> customizers) {
return new SmartInitializingSingleton() {
@Override
public void afterSingletonsInstantiated() {
for (RestTemplate restTemplate : LoadBalancerAutoConfiguration.this.restTemplates) {
for (RestTemplateCustomizer customizer : customizers) {
customizer.customize(restTemplate);
}
}
}
};
}
@Autowired(required = false)
private List<LoadBalancerRequestTransformer> transformers = Collections.emptyList();
@Bean
@ConditionalOnMissingBean
public LoadBalancerRequestFactory loadBalancerRequestFactory(
LoadBalancerClient loadBalancerClient) {
return new LoadBalancerRequestFactory(loadBalancerClient, transformers);
}
@Configuration
@ConditionalOnMissingClass("org.springframework.retry.support.RetryTemplate")
static class LoadBalancerInterceptorConfig {
@Bean
public LoadBalancerInterceptor ribbonInterceptor(
LoadBalancerClient loadBalancerClient,
LoadBalancerRequestFactory requestFactory) {
return new LoadBalancerInterceptor(loadBalancerClient, requestFactory);
}
@Bean
@ConditionalOnMissingBean
public RestTemplateCustomizer restTemplateCustomizer(
final LoadBalancerInterceptor loadBalancerInterceptor) {
return new RestTemplateCustomizer() {
@Override
public void customize(RestTemplate restTemplate) {
List<ClientHttpRequestInterceptor> list = new ArrayList<>(
restTemplate.getInterceptors());
list.add(loadBalancerInterceptor);
restTemplate.setInterceptors(list);
}
};
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
这段自动装配的代码的含义不难理解,就是利用了RestTempllate的拦截器,使用RestTemplateCustomizer对所有标注了@LoadBalanced的RestTemplate Bean添加了一个LoadBalancerInterceptor拦截器,而这个拦截器的作用就是对请求的URI进行转换获取到具体应该请求哪个服务实例ServiceInstance。
那么为什么
@LoadBalanced
@Autowired(required = false)
private List<RestTemplate> restTemplates = Collections.emptyList();
- 1
- 2
- 3
这个restTemplates能够将所有标注了@LoadBalanced的RestTemplate自动注入进来呢?这就要说说@Autowired注解和@Qualifier这两个注解了。
大家日常使用很多都是用@Autowired来注入一个bean,其实@Autowired还可以注入List和Map,比如我定义两个Bean:
@RestController
public class MyController {
<span class="token annotation punctuation">@Autowired</span><span class="token punctuation">(</span>required <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">)</span>
<span class="token keyword">private</span> <span class="token class-name">List</span><span class="token generics"><span class="token punctuation"><</span><span class="token class-name">User</span><span class="token punctuation">></span></span> users <span class="token operator">=</span> <span class="token class-name">Collections</span><span class="token punctuation">.</span><span class="token function">emptyList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token annotation punctuation">@Autowired</span><span class="token punctuation">(</span>required <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">)</span>
<span class="token keyword">private</span> <span class="token class-name">Map</span><span class="token generics"><span class="token punctuation"><</span><span class="token class-name">String</span><span class="token punctuation">,</span><span class="token class-name">User</span><span class="token punctuation">></span></span> userMap <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">HashMap</span><span class="token generics"><span class="token punctuation"><</span><span class="token punctuation">></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token annotation punctuation">@RequestMapping</span><span class="token punctuation">(</span><span class="token string">"/list"</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token class-name">Object</span> <span class="token function">listUsers</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
<span class="token keyword">return</span> users<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token annotation punctuation">@RequestMapping</span><span class="token punctuation">(</span><span class="token string">"/map"</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token class-name">Object</span> <span class="token function">mapUsers</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
<span class="token keyword">return</span> userMap<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
在controller中通过:
@Autowired(required = false)
private List<User> users = Collections.emptyList();
@Autowired(required = false)
private Map<String,User> userMap = new HashMap<>();
- 1
- 2
- 3
- 4
- 5
就可以自动将两个bean注入进来,当注入map的时候,map的key必须是String类型,然后bean name将作为map的key,本例,map中将有两个key分别为user1和user2,value分别为对应的User Bean实例。
访问http://localhost:8080/map:
{
"user1": {
"id": "1",
"name": "a"
},
"user2": {
"id": "2",
"name": "b"
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
访问http://localhost:8080/list:
[
{
"id": "1",
"name": "a"
},
{
"id": "2",
"name": "b"
}
]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
然后我们给user1和user2分别打上@Qualifier修饰符:
@Bean("user1")
@Qualifier("valid")
User user1() {
return new User("1", "a");
}
@Bean("user2")
@Qualifier("invalid")
User user2() {
return new User("2", "b");
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
然后将controller中的user list 和user map分别也打上@Qualifier修饰符:
@RestController
public class MyController {
<span class="token annotation punctuation">@Autowired</span><span class="token punctuation">(</span>required <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">)</span>
<span class="token annotation punctuation">@Qualifier</span><span class="token punctuation">(</span><span class="token string">"valid"</span><span class="token punctuation">)</span>
<span class="token keyword">private</span> <span class="token class-name">List</span><span class="token generics"><span class="token punctuation"><</span><span class="token class-name">User</span><span class="token punctuation">></span></span> users <span class="token operator">=</span> <span class="token class-name">Collections</span><span class="token punctuation">.</span><span class="token function">emptyList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token annotation punctuation">@Autowired</span><span class="token punctuation">(</span>required <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">)</span>
<span class="token annotation punctuation">@Qualifier</span><span class="token punctuation">(</span><span class="token string">"invalid"</span><span class="token punctuation">)</span>
<span class="token keyword">private</span> <span class="token class-name">Map</span><span class="token generics"><span class="token punctuation"><</span><span class="token class-name">String</span><span class="token punctuation">,</span><span class="token class-name">User</span><span class="token punctuation">></span></span> userMap <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">HashMap</span><span class="token generics"><span class="token punctuation"><</span><span class="token punctuation">></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token annotation punctuation">@RequestMapping</span><span class="token punctuation">(</span><span class="token string">"/list"</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token class-name">Object</span> <span class="token function">listUsers</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
<span class="token keyword">return</span> users<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token annotation punctuation">@RequestMapping</span><span class="token punctuation">(</span><span class="token string">"/map"</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token class-name">Object</span> <span class="token function">mapUsers</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
<span class="token keyword">return</span> userMap<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
那么所有标注了@Qualifier(“valid”)的user bean都会自动注入到List users中去(本例是user1),所有标注了@Qualifier(“invalid”)的user bean都会自动注入到Map<String,User> userMap中去(本例是user2),我们再次访问上面两个url:
访问http://localhost:8080/list:
[
{
"id": "1",
"name": "a"
}
]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
访问http://localhost:8080/map:
{
"user2": {
"id": "2",
"name": "b"
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
看到这里我们可以理解@LoadBalanced的用处了,其实就是一个修饰符,和@Qualifier一样,比如我们给user1打上@LoadBalanced:
@Bean("user1")
@LoadBalanced
User user1() {
return new User("1", "a");
}
@Bean("user2")
User user2() {
return new User("2", "b");
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
然后controller中给List users打上@LoadBalanced注解:
@Autowired(required = false)
@LoadBalanced
private List<User> users = Collections.emptyList();
- 1
- 2
- 3
访问http://localhost:8080/list:
[
{
"id": "1",
"name": "a"
}
]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
和@Qualifier注解效果一样,只有user1被注入进了List,user2没有修饰符,没有被注入进去。
另外当spring容器中有多个相同类型的bean的时候,可以通过@Qualifier来进行区分,以便在注入的时候明确表明你要注入具体的哪个bean,消除歧义。
@LoadBalanced注解原理的更多相关文章
- 深入理解@LoadBalanced注解的实现原理与客户端负载均衡
前提 在阅读这篇博客之前,希望你对SpringCloud套件熟悉和理解,更希望关注下微服务开发平台 概述 在使用springcloud ribbon客户端负载均衡的时候,可以给RestTemplate ...
- Spring 注解原理(三)@Qualifier @Value
Spring 注解原理(三)@Qualifier @Value Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) 一.Aut ...
- 为何一个@LoadBalanced注解就能让RestTemplate拥有负载均衡的能力?【享学Spring Cloud】
每篇一句 你应该思考:为什么往往完成比完美更重要? 前言 在Spring Cloud微服务应用体系中,远程调用都应负载均衡.我们在使用RestTemplate作为远程调用客户端的时候,开启负载均衡极其 ...
- Java Android 注解(Annotation) 及几个常用开源项目注解原理简析
不少开源库(ButterKnife.Retrofit.ActiveAndroid等等)都用到了注解的方式来简化代码提高开发效率. 本文简单介绍下 Annotation 示例.概念及作用.分类.自定义. ...
- java基础解析系列(六)---深入注解原理及使用
java基础解析系列(六)---注解原理及使用 java基础解析系列(一)---String.StringBuffer.StringBuilder java基础解析系列(二)---Integer ja ...
- Spring 注解原理(一)组件注册
Spring 注解原理(一)组件注册 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) 当我们需要使用 Spring 提供的 ...
- java基础解析系列(六)---注解原理及使用
java基础解析系列(六)---注解原理及使用 java基础解析系列(一)---String.StringBuffer.StringBuilder java基础解析系列(二)---Integer缓存及 ...
- Spring 中常用注解原理剖析
前言 Spring 框架核心组件之一是 IOC,IOC 则管理 Bean 的创建和 Bean 之间的依赖注入,对于 Bean 的创建可以通过在 XML 里面使用 <bean/> 标签来配置 ...
- Spring注解原理
一.注解的基本概念和原理及其简单实用 注解(Annotation)提供了一种安全的类似注释的机制,为我们在代码中添加信息提供了一种形式化得方法,使我们可以在稍后某个时刻方便的使用这些数据(通过解析注解 ...
- 浅谈SpringBoot核心注解原理
SpringBoot核心注解原理 今天跟大家来探讨下SpringBoot的核心注解@SpringBootApplication以及run方法,理解下springBoot为什么不需要XML,达到零配置 ...
随机推荐
- uoj348【WC2018】州区划分
题目链接 直接讲吨吨吨给的标准做法吧.记\(f(i,j)\)表示各个州(可以重叠)的城市数量之和为i,这些州的并集为j的方案数,反正若有两个州之间有交集最后的\(|j|\)会不等于\(i\).有 \( ...
- 深入剖析Sgementation fault原理
深入剖析Sgementation fault原理 前言 我们在日常的编程当中,我们很容易遇到的一个程序崩溃的错误就是segmentation fault,在本篇文章当中将主要分析段错误发生的原因! S ...
- 解决在JS中阻止定时器“重复”开启问题、Vue中定时器的使用
1.问题描述 在一些需求开发中.需要设定软件提供服务的时间段(营业时间).这时可以选择定时器来实现.可以选择让定时器每隔一段时间检测当前时间是否在服务时间.到达服务时间.进入服务状态.未到服务时间.进 ...
- 齐博x1token字段,请务加在请求地址的头部header
如下图所示,你必须在请求的头部加上 token参数,主要原因有两个.第一点,这个是登录标志,因为接口访问用不了cookie,所以只能通过这个header请求标志判断用户是否已经登录.第二点,系统有时候 ...
- 小米MIUI禁止系统更新
删除downloaded_rom的文件夹,随便找一个文件(文件,不是文件夹),重名为downloaded_rom(是把一个文件重命名),这样系统后台偷偷下载时,就不知道该存放更新包的文件,就无法偷偷更 ...
- 关于Object.keys()和Object.values()的使用
关于Object.keys()和Object.values()的使用 1. 关于Object.keys() 1) 处理对象,返回可枚举的所有可枚举属性的字符串数组 let person ={ name ...
- 题解 CF803A Maximal Binary Matrix
Luogu codeforces 前言 模拟赛原题.. 好好一道送分被我硬打成爆蛋.. \(\sf{Solution}\) 看了一波数据范围,感觉能 dfs 骗分. 骗成正解了. 大概就是将这个 \( ...
- 七、docker镜像私有仓库
在Docker中,当我们执行 docker pull xxx 的时候 ,它实际上是从 hub.docker.com 这个地址去查找,这就是 Docker 公司为我们提供的公共仓库.在工作中,我们不可能 ...
- Linux网络管理命令
Linux网络管理命令 ifconfig 用于配置网卡ip地址信息等网络参数或显示网络接口状态,类似于windows的ipconfig命令. 可以用这个工具来临时性的配置网卡的IP地址.掩码.广播地址 ...
- Day10:for循环结构的使用详解
for循环 将0~100内的奇.偶数分别求和 思路 第一步先将0~100以内的奇.偶数分成两队,第二步使奇数累加.ou'shu public class ForCirculate{ public st ...