spring boot 2.x spring cloud Greenwich.SR1 @SpringCloudApplication注解、@EnableDiscoveryClient注解详解
文章目录
@SpringCloudApplication
注解
最近再看springcloud的小部分源码的时候,发现了一个有意思的注解@SpringCloudApplication
,我们先看下注解的内容
/**
* @author Spencer Gibb
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public @interface SpringCloudApplication {
}
可以看到,这个注解,是由三个注解组合而成@SpringBootApplication
、@EnableDiscoveryClient
、@EnableCircuitBreaker
;我们可以直接使用这个注解,来使用springcloud的一些组合功能,比如断路器(hystrix)以及客户端(服务的提供者)注册到注册中心;
1.1、@SpringBootApplication
注解
这个注解,大家都很熟悉了,就不解释了,详细的,也可以参看《springboot2.0 主程序类@SpringBootApplication详解,@SpringBootConfiguration,@EnableAutoConfiguration》;
1.2、@EnableDiscoveryClient
注解
这个注解的作用,开启客户端的注册功能,把当前应用,注册到注册中心中;@EnableEurekaClient
注解,只支持eureka作为注册中心,而@EnableDiscoveryClient
,支持其他的注册中心(consul,eureka等);
先看下这个注解的定义内容
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(EnableDiscoveryClientImportSelector.class)
public @interface EnableDiscoveryClient {
/**
* If true, the ServiceRegistry will automatically register the local server.
* @return - {@code true} if you want to automatically register.
*/
boolean autoRegister() default true;
}
这个注解中,有个autoRegister
属性,默认为true;,表示是否自动这个服务本地服务;
注解中,还通过@Import
注解,为容器中导入了EnableDiscoveryClientImportSelector类;关于@Import
注解,还有不熟悉的,可以参看《spring注解 @Import的使用,ImportSelector接口,ImportBeanDefinitionRegistrar接口》;
我们详细看下,EnableDiscoveryClientImportSelector
类中(主要代码),为容器导入了什么组件;
@Order(Ordered.LOWEST_PRECEDENCE - 100)
public class EnableDiscoveryClientImportSelector
extends SpringFactoryImportSelector<EnableDiscoveryClient> {
@Override
public String[] selectImports(AnnotationMetadata metadata) {
//获取父级中为容器导入的组件的数组,默认为空数组
String[] imports = super.selectImports(metadata);
//获取注解的详细
AnnotationAttributes attributes = AnnotationAttributes.fromMap(
metadata.getAnnotationAttributes(getAnnotationClass().getName(), true));
//获取注解中, boolean autoRegister() default true;的属性,默认就是true
boolean autoRegister = attributes.getBoolean("autoRegister");
if (autoRegister) {
//为组件中新增AutoServiceRegistrationConfiguration这个自动装配类
List<String> importsList = new ArrayList<>(Arrays.asList(imports));
importsList.add(
"org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration");
imports = importsList.toArray(new String[0]);
}
else {
//如果为flase,为容器中,
//设置spring.cloud.service-registry.auto-registration.enabled的属性为true
//类型在yaml中,设置这个属性为true
Environment env = getEnvironment();
if (ConfigurableEnvironment.class.isInstance(env)) {
ConfigurableEnvironment configEnv = (ConfigurableEnvironment) env;
LinkedHashMap<String, Object> map = new LinkedHashMap<>();
map.put("spring.cloud.service-registry.auto-registration.enabled", false);
MapPropertySource propertySource = new MapPropertySource(
"springCloudDiscoveryClient", map);
configEnv.getPropertySources().addLast(propertySource);
}
}
//返回注入的组件,也就是上面的AutoServiceRegistrationConfiguration配置类
return imports;
}
根据上面的代码,可以知道,使用@EnableDiscoveryClient
注解,为容器中,注入了一个org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration
的配置类,这个类,在spring-cloud-commons-2.1.1.RELEASE.jar
中的对应包下,我看下这个配置类,又为容器中,注入了什么内容
/**
* @author Spencer Gibb
*/
@Configuration
@EnableConfigurationProperties(AutoServiceRegistrationProperties.class)
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
public class AutoServiceRegistrationConfiguration {
}
可以看到,没有为容器中注入组件,是一个空的配置类;如果为容器中注入一个空的配置类,是不是没有意义?会不会是其他的组件(配置类)在使用之前,必须要依赖这个组件,我直接搜索了一下,调用AutoServiceRegistrationConfiguration
这个类的地方;还真搜索到了2个地方;如图所示:
第二个就是注解对象本身,不在细说;
我们看第一个,调用的配置类org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration
@Configuration
@Import(AutoServiceRegistrationConfiguration.class)
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
public class AutoServiceRegistrationAutoConfiguration {
@Autowired(required = false)
private AutoServiceRegistration autoServiceRegistration;
@Autowired
private AutoServiceRegistrationProperties properties;
@PostConstruct
protected void init() {
if (this.autoServiceRegistration == null && this.properties.isFailFast()) {
throw new IllegalStateException("Auto Service Registration has "
+ "been requested, but there is no AutoServiceRegistration bean");
}
}
}
这个配置类中,也使用了@Import
导入这个AutoServiceRegistrationConfiguration
;配置类中,并没有注入其他的组件,只是一个默认的初始化方法;
我们再看下,什么地方调用默认自动装配了AutoServiceRegistrationAutoConfiguration
;我们都知道,默认装配类,一般都是写到到spring.factories
,我们看下文件的内容
这个类,被springboot自动装配了;
所以说,理论上,我们是不需要加@EnableDiscoveryClient
注解的,跟不需要加@EnableEurekaClient
注解一样,也会被注册到注册中心中;
1.3、@EnableCircuitBreaker
注解
这个注解,是断路器的注解,开启断路器,另外开启断路器的注解@EnableHystrix
,我们先看下注解的定义
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@EnableCircuitBreaker
public @interface EnableHystrix {
}
可以看到,@EnableHystrix
注解,本质上就是使用的@EnableCircuitBreaker
注解;