在使用springcloud ribbon客户端负载均衡的时候,能够给RestTemplate bean 加一个@LoadBalanced注解,就能让这个RestTemplate在请求时拥有客户端负载均衡的能力:html
@Bean @LoadBalanced RestTemplate restTemplate() { return new RestTemplate(); }
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 { }
惟一不一样的地方就是多了一个@Qulifier注解.java
搜索@LoadBalanced注解的使用地方,发现只有一处使用了,在LoadBalancerAutoConfiguration这个自动装配类中:web
@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); } }; } }
那么为何spring
@LoadBalanced @Autowired(required = false) private List<RestTemplate> restTemplates = Collections.emptyList();这个restTemplates可以将全部标注了@LoadBalanced的RestTemplate自动注入进来呢?这就要说说@Autowired注解和@Qualifier这两个注解了。
你们平常使用不少都是用@Autowired来注入一个bean,其实@Autowired还能够注入List和Map,好比我定义两个Bean:app
@Bean("user1") User user1() { return new User("1", "a"); } @Bean("user2")) User user2() { return new User("2", "b"); }
import com.example.demo.domain.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @RestController public class MyController { @Autowired(required = false) private List<User> users = Collections.emptyList(); @Autowired(required = false) private Map<String,User> userMap = new HashMap<>(); @RequestMapping("/list") public Object listUsers() { return users; } @RequestMapping("/map") public Object mapUsers() { return userMap; } }
@Autowired(required = false) private List<User> users = Collections.emptyList(); @Autowired(required = false) private Map<String,User> userMap = new HashMap<>();
访问http://localhost:8080/map:负载均衡
{ "user1": { "id": "1", "name": "a" }, "user2": { "id": "2", "name": "b" } }
[ { "id": "1", "name": "a" }, { "id": "2", "name": "b" } ]
@Bean("user1") @Qualifier("valid") User user1() { return new User("1", "a"); } @Bean("user2") @Qualifier("invalid") User user2() { return new User("2", "b"); }
import com.example.demo.domain.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @RestController public class MyController { @Autowired(required = false) @Qualifier("valid") private List<User> users = Collections.emptyList(); @Autowired(required = false) @Qualifier("invalid") private Map<String,User> userMap = new HashMap<>(); @RequestMapping("/list") public Object listUsers() { return users; } @RequestMapping("/map") public Object mapUsers() { return userMap; } }那么全部标注了@Qualifier("valid")的user bean都会自动注入到List<user> users中去(本例是user1),全部标注了@Qualifier("invalid")的user bean都会自动注入到Map<String,User> userMap中去(本例是user2),咱们再次访问上面两个url:
访问http://localhost:8080/list:dom
[ { "id": "1", "name": "a" } ]访问http://localhost:8080/map:
{ "user2": { "id": "2", "name": "b" } }
@Bean("user1") @LoadBalanced User user1() { return new User("1", "a"); } @Bean("user2") User user2() { return new User("2", "b"); }
@Autowired(required = false) @LoadBalanced private List<User> users = Collections.emptyList();
[ { "id": "1", "name": "a" } ]
另外当spring容器中有多个相同类型的bean的时候,能够经过@Qualifier来进行区分,以便在注入的时候明确代表你要注入具体的哪一个bean,消除歧义。ide