云霄建设局网站,后台网站怎么做视频,江苏省建设厅官网,金环建设集团网站添加了nacos的maven依赖之后#xff0c;只需要在启动类上加一个EnableDiscoveryClient注解就可以实现服务注册#xff0c;这个注解为什么可以实现#xff1f;
EnableDiscoveryClient注解
进去到EnableDiscoveryClient注解之后#xff0c;只有简单的几行代码#xff1a; …添加了nacos的maven依赖之后只需要在启动类上加一个EnableDiscoveryClient注解就可以实现服务注册这个注解为什么可以实现
EnableDiscoveryClient注解
进去到EnableDiscoveryClient注解之后只有简单的几行代码
Target(ElementType.TYPE)
Retention(RetentionPolicy.RUNTIME)
Documented
Inherited
Import(EnableDiscoveryClientImportSelector.class)
public interface EnableDiscoveryClient {boolean autoRegister() default true;}在这里唯一特殊的地方就是Import(EnableDiscoveryClientImportSelector.class)这个注解但是这个Import注解又是起什么作用的
Import注解的作用
我实际操作下来感觉Import注解的作用其实和Configuration注解Component等注解的作用差不多都是将当前类交给Spring容器管理。
创建的测试类如下
Target(ElementType.TYPE)
Retention(RetentionPolicy.RUNTIME)
Inherited
Import(TwoModuleClientImportSelect.class)
public interface StartImport {boolean registerOther() default true;
}public abstract class AbsTwoModuleFactoryImportSelectorT implements ImportSelector {private ClassT annotationClass;protected AbsTwoModuleFactoryImportSelector() {this.annotationClass (ClassT) GenericTypeResolver.resolveTypeArgument(this.getClass(), AbsTwoModuleFactoryImportSelector.class);}Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {AnnotationAttributes attributes AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(this.annotationClass.getName(), true));return new String[0];}protected ClassT getAnnotationClass() {return this.annotationClass;}
}Slf4j
public class TwoModuleClientImportSelect extends AbsTwoModuleFactoryImportSelectorStartImport {Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {String[] imports super.selectImports(importingClassMetadata);AnnotationAttributes attributes AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(getAnnotationClass().getName(), true));Boolean auto attributes.getBoolean(registerOther);if (auto) {ListString addStr new ArrayList(Arrays.asList(imports));addStr.add(com.zhuruilin.sample.testImport.TwoModuleOtherConfiguration);imports addStr.toArray(new String[0]);}return imports;}
}Configuration(proxyBeanMethods false)
Slf4j
public class TwoModuleOtherConfiguration {PostConstructpublic void testImport() {log.info(TwoModuleOtherConfiguration 使用 PostConstruct 注解的地方);}
}总共新建了四个类
StartImport 注解抽象类AbsTwoModuleFactoryImportSelector实现了ImportSelector接口并且使用了泛型TwoModuleClientImportSelect继承了上面的抽象类并且指定泛型为StartImport注解TwoModuleOtherConfiguration配置类在TwoModuleClientImportSelect中有使用到这个类的包路径。
操作如下
在启动类中不加StartImport 注解启动会打印 log.info(“TwoModuleOtherConfiguration 使用 PostConstruct 注解的地方”)TwoModuleOtherConfiguration 类中去掉Configuration注解在启动类中加上StartImport 还是会打印日志。去掉Configuration注解启动类中去掉StartImport注解不会打印日志加上Configuration注解和StartImport注解会打印日志。
可以看出其实Import的注解的作用就是将类交给spring容器管理好处就是不用修改使用类的代码如果需要将第三方jar包类的一个类可以直接使用Autowired注解那就可以在Import注解中指定这个类而不需要在jar包里加上Component类似的注解。
Import注解有三种使用方式也可以直接指定一个类
Target(ElementType.TYPE)
Retention(RetentionPolicy.RUNTIME)
Inherited
Import({TwoModuleClientImportSelect.class, TwoModuleDirectBean.class})
public interface StartImport {boolean registerOther() default true;}这里TwoModuleDirectBean类就是直接指定的TwoModuleClientImportSelect则是使用实现ImportSelector接口的方式来第三种方式可以通过实现ImportBeanDefinitionRegistrar 接口的方式来实现。
public class TwoModuleThirdWay implements ImportBeanDefinitionRegistrar {Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {RootBeanDefinition rbd new RootBeanDefinition(TwoModuleOtherConfiguration.class);registry.registerBeanDefinition(rootBeanDefinition, rbd);}
}Target(ElementType.TYPE)
Retention(RetentionPolicy.RUNTIME)
Inherited
//Import({TwoModuleClientImportSelect.class, TwoModuleDirectBean.class, TwoModuleThirdWay.class})
Import({TwoModuleDirectBean.class, TwoModuleThirdWay.class})
public interface StartImport {boolean registerOther() default true;}启动项目之后也是可以看到打印日志的后两种感觉都是间接的方式来创建的。
EnableDiscoveryClientImportSelector类
EnableDiscoveryClientImportSelector类也是通过实现了ImportSelector接口的方式来管理AutoServiceRegistrationConfiguration类的只不过中间又加了两层。
新建测试工程并且加上nacos依赖加上EnableDiscoveryClient注解在EnableDiscoveryClientImportSelector类中开始debug。运行到最后可以发现最终返回的imports数组就只有一个元素就是只有org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration。
spring.factories
在spring-cloud-starter-alibaba-nacos-discovery这个项目中就用到了spring.factories具体内容如下
org.springframework.boot.autoconfigure.EnableAutoConfiguration\com.alibaba.cloud.nacos.discovery.NacosDiscoveryAutoConfiguration,\com.alibaba.cloud.nacos.endpoint.NacosDiscoveryEndpointAutoConfiguration,\com.alibaba.cloud.nacos.registry.NacosServiceRegistryAutoConfiguration,\com.alibaba.cloud.nacos.discovery.NacosDiscoveryClientConfiguration,\com.alibaba.cloud.nacos.discovery.reactive.NacosReactiveDiscoveryClientConfiguration,\com.alibaba.cloud.nacos.discovery.configclient.NacosConfigServerAutoConfiguration,\com.alibaba.cloud.nacos.loadbalancer.LoadBalancerNacosAutoConfiguration,\com.alibaba.cloud.nacos.NacosServiceAutoConfigurationorg.springframework.cloud.bootstrap.BootstrapConfiguration\com.alibaba.cloud.nacos.discovery.configclient.NacosDiscoveryClientConfigServiceBootstrapConfigurationorg.springframework.context.ApplicationListener\com.alibaba.cloud.nacos.discovery.logging.NacosLoggingListener这里先看服务注册相关的先关注 org.springframework.boot.autoconfigure.EnableAutoConfiguration 这个配置项的这个配置项后面跟了一大堆nacos的对象作用是在项目启动的时候会扫描spring.factories文件并且加载这些对象到容器中从而实现了自定义的自动配置。 这里查看NacosServiceRegistryAutoConfiguration类点进去可以看到
Configuration(proxyBeanMethods false)
EnableConfigurationProperties
ConditionalOnNacosDiscoveryEnabled
ConditionalOnProperty(value spring.cloud.service-registry.auto-registration.enabled,matchIfMissing true)
AutoConfigureAfter({ AutoServiceRegistrationConfiguration.class,AutoServiceRegistrationAutoConfiguration.class,NacosDiscoveryAutoConfiguration.class })
public class NacosServiceRegistryAutoConfiguration {Beanpublic NacosServiceRegistry nacosServiceRegistry(NacosServiceManager nacosServiceManager,NacosDiscoveryProperties nacosDiscoveryProperties) {return new NacosServiceRegistry(nacosServiceManager, nacosDiscoveryProperties);}BeanConditionalOnBean(AutoServiceRegistrationProperties.class)public NacosRegistration nacosRegistration(ObjectProviderListNacosRegistrationCustomizer registrationCustomizers,NacosDiscoveryProperties nacosDiscoveryProperties,ApplicationContext context) {return new NacosRegistration(registrationCustomizers.getIfAvailable(),nacosDiscoveryProperties, context);}BeanConditionalOnBean(AutoServiceRegistrationProperties.class)public NacosAutoServiceRegistration nacosAutoServiceRegistration(NacosServiceRegistry registry,AutoServiceRegistrationProperties autoServiceRegistrationProperties,NacosRegistration registration) {return new NacosAutoServiceRegistration(registry,autoServiceRegistrationProperties, registration);}}spring.factories的作用就是将当前项目的对象可以交给外部项目使用就是A项目中包含B项目但是B项目中的类不会被A项目管理哪怕加上了Configuration注解但是在A项目中也是无法发现的这个时候就可以在B项目中的spring.factories指定一些类这些类就可以在A项目中使用AutoWired注解来使用了。
并且在B类中spring.factories中加载的类如果这个类中还使用了Bean注解的方式来创建bean在A项目中也是可以使用的。
Configuration(proxyBeanMethods false)
proxyBeanMethods的作用 首先引出两个概念Full 全模式Lite 轻量级模式 Full(proxyBeanMethods true) :proxyBeanMethods参数设置为true时即为Full 全模式。 该模式下注入容器中的同一个组件无论被取出多少次都是同一个bean实例即单实例对象在该模式下SpringBoot每次启动都会判断检查容器中是否存在该组件 Lite(proxyBeanMethods false) :proxyBeanMethods参数设置为false时即为Lite 轻量级模式。该模式下注入容器中的同一个组件无论被取出多少次都是不同的bean实例即多实例对象在该模式下SpringBoot每次启动会跳过检查容器中是否存在该组件 什么时候用Full全模式什么时候用Lite轻量级模式 当在你的同一个Configuration配置类中注入到容器中的bean实例之间有依赖关系时建议使用Full全模式 当在你的同一个Configuration配置类中注入到容器中的bean实例之间没有依赖关系时建议使用Lite轻量级模式以提高springboot的启动速度和性能 EnableConfigurationProperties
这个注解的作用是将使用了ConfigurationProperties(prefix “xx”)注解的类创建对象也就是如果在A类上加上了ConfigurationProperties注解B类上只有Configuration注解并没有在B类上加上EnableConfigurationProperties(A.class)注解那么这个时候其实还是不能用A类对象的因为并没有将A类创建。解决的办法可以是直接在A类上加上Component类似的注解也可以在加了Configuration类似的注解类上比如B类中再加上EnableConfigurationProperties(A.class)注解也可以实现一样的效果。
但是在NacosServiceRegistryAutoConfiguration类上可以看见并没有指定类名刚开始我也这么干的但是启动会报错(因为我有直接使用Autowired来注入A对象的代码)提示找不到这个A类。之后我就发现在AutoConfigureAfter注解中的AutoServiceRegistrationConfiguration类上有了EnableConfigurationProperties(AutoServiceRegistrationProperties.class)的注解所以在NacosServiceRegistryAutoConfiguration类中可以使用AutoServiceRegistrationProperties配置类
NacosServiceRegistryAutoConfiguration
在NacosServiceRegistryAutoConfiguration类中使用Bean创建来了三个bean对象一个是NacosServiceRegistry一个是NacosRegistration还有一个是NacosAutoServiceRegistration并且可以看到第三个bean创建的方法参数就用到了前两个bean对象。
NacosServiceRegistryAutoConfiguration类实现了抽象类AbstractAutoServiceRegistration(后面为了省事就叫自动注册抽象类)而这个自动注册抽象类又实现了AutoServiceRegistration, ApplicationContextAware, ApplicationListener WebServerInitializedEvent 接口。
AutoServiceRegistration 这个类就是NacosServiceRegistryAutoConfiguration和自动注册抽象类的顶级接口ApplicationContextAware 实现了这个接口就可以取到所有创建的bean对象。ApplicationListener WebServerInitializedEvent 监听web 容器启动事件启动默认内置容器tomcat的时候会触发监听器的onApplicationEvent方法。
在创建NacosAutoServiceRegistration对象的时候有使用到了NacosServiceRegistry这个对象这个对象实现了ServiceRegistry接口这个接口是spring.cloud开放的如果是用eureka的也会有一个类去实现这个接口。只要看NacosServiceRegistry中的register(Registration registration)方法。主要流程就是根据serverAddrspring.application.name等等配置的信息构建出一个Instance对象这个Instance对象就是表示当前服务的信息的最后再发送一个POST请求到nacos服务端这样就大致完成了一个服务注册的过程。
总结过程
在spring.factories文件中加上配置类NacosServiceRegistryAutoConfiguration在NacosServiceRegistryAutoConfiguration配置类中使用Bean的方式创建出NacosServiceRegistryNacosRegistrationNacosAutoServiceRegistration三个bean。NacosAutoServiceRegistration继承了抽象类AbstractAutoServiceRegistration这个抽象类实现了ApplicationListener WebServerInitializedEvent 接口监听了容器启动事件在容器启动的时候会收到通知触发抽象类的onApplicationEvent方法最终会调用NacosAutoServiceRegistration构造函数中的ServiceRegistry对象也就是nacos中的具体实现类NacosServiceRegistry调用了NacosServiceRegistry类中的egister(Registration registration)方法之后会将当前服务信息和nacos服务端信息整合成一个Instance实例对象用这个Instance实例对象来表示当前服务信息。最后会发送一个POST请求将Instance中存储的信息发送给nacos服务端完成服务注册。