Springboot基于enable模块驱动

匿名 (未验证) 提交于 2019-12-03 00:00:02
enable作为模块驱动在Spring Farmework、Spring Boot、Spring Cloud使用,都是通过注解的形式以@enable作为前缀,一些常用注解如 | 框架 | 注解 | 模块 | | --- | --- | --- | | Spring Framework | @EnableWebMvc | Web MVC模块 | | Spring Framework | @EnableTransactionmanagement | Web MVC模块 | | Spring Framework | @EnableCacheing | Cacheing模块 | | Spring Framework | @EnableMBeanExport | JMX模块 | | Spring Framework | @EnableWebFlux | Web Flux模块 | | Spring Framework | @EnableAspectJAutoProxy | AspectJ模块 | | Spring Boot | @EnableAutoConfiguration | 自动装配模块 | | Spring Boot | @EnableWebManagementContext | Actuator模块 | | Spring Boot | @EnableConfigurationProperties | 配置属性绑定模块 | | Spring Boot | @EnableOauth2Sso | OAuth2单独登录模块 | | Spring Cloud | @EnableEurekaServer | eureka服务模块 | | Spring Cloud | @EnableConfigServer | 配置服务器模块 | | Spring Cloud | @EnableFeignClients | Feign客户端模块 | | Spring Cloud | @EnableZuulProxy | 服务网关zuul模块 | | Spring Cloud | @EnableCircuitBreaker | 服务熔断模块 | ## 如何自定义enable开发? ### 基于ImportSelector实现注解驱动 #### 自定义接入类型 Access为接入类型的接口,下文的RPC接入和REST接入基于这个实现,定义两个接口,一个为启动,一个停止,内部嵌套一个枚举用于标识是哪一种接入 ``` public interface Access { /** * 初始化配置 */ void start(); /** * 销毁配置 */ void stop(); enum Type{ REST, RPC } } ``` #### 定义RPC和REST的实现 REST实现,只是简单的打印方法 ``` public class RestAccess implements Access{ @Override public void start() { System.out.println("rest接入配置"); } @Override public void stop() { System.out.println("rest接入销毁配置"); } } ``` RPC实现 ``` public class RpcAccess implements Access{ @Override public void start() { System.out.println("rpc接入配置"); } @Override public void stop() { System.out.println("rpc接入销毁配置"); } } ``` #### 自定义注解EnableAccess 接入类型为RPC或者REST,AccessImportSelector在下一步骤实现 ``` @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @Import(AccessImportSelector.class) public @interface EnableAccess { /** * 接入类型 * @return */ Access.Type type(); } ``` #### 实现ImportSelector 定义AccessImportSelector实现ImportSelector,分别获取注解信息,根据注解获取接入类型,根据接入类型选择不同的接入类型 ``` public class AccessImportSelector implements ImportSelector{ @Override public String[] selectImports(AnnotationMetadata annotationMetadata) { //读取EnableAccess中所有的属性方法 Map annotationAttributes = annotationMetadata.getAnnotationAttributes(EnableAccess.class.getName()); //获取属性为type的属性方法 Access.Type type = (Access.Type )annotationAttributes.get("type"); //导入的类名称数组 String [] importClassName = new String[0]; switch (type){ case RPC: //设置为RPC,返回RpcAccess组件 importClassName = new String[]{RpcAccess.class.getName()}; break; case REST: //设置为REST,返回RestAccess组件 importClassName = new String[]{RestAccess.class.getName()}; } return importClassName; } } ``` #### 使用 在primarySource也就是这里的DemoApplication上使用注解EnableAccess,选择接入方式,就会初始化不通的接入组件 ``` @SpringBootApplication @EnableAccess(type=Access.Type.REST) public class DemoApplication { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(DemoApplication.class, args); Access access = context.getBean(Access.class); access.start(); access.stop(); } } ``` ### 基于ImportBeanDefinitionRegistrar实现注解驱动 这里其它步骤一样,主要区别是注解里面Import的类变了,这里是基于基于ImportBeanDefinitionRegistrar实现注解驱动实现 #### 自定义ImportBeanDefinitionRegistrar ``` public class AccessImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) { ImportSelector importSelector = new AccessImportSelector(); //筛选class名称集合 String[] selectedClassNames = importSelector.selectImports(annotationMetadata); Stream.of(selectedClassNames) .map(BeanDefinitionBuilder::genericBeanDefinition) .map(BeanDefinitionBuilder::getBeanDefinition) .forEach(beanDefinition ->{ //注册beanDefinition到beanDefinitionRegistry BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition,beanDefinitionRegistry); }); } } ``` #### EnableAccess注解变更 这里import导入了AccessImportBeanDefinitionRegistrar ``` @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @Import(AccessImportBeanDefinitionRegistrar.class) public @interface EnableAccess { /** * 接入类型 * @return */ Access.Type type(); } ``` ### 实现 #### RPC接入 type=Access.Type.RPC ``` @SpringBootApplication @EnableAccess(type=Access.Type.RPC) public class DemoApplication { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(DemoApplication.class, args); Access access = context.getBean(Access.class); access.start(); access.stop(); } } ``` ![file](https://img2018.cnblogs.com/blog/1747067/201909/1747067-20190910091130214-1566835043.jpg) #### REST接入 type=Access.Type.REST ``` @SpringBootApplication @EnableAccess(type=Access.Type.REST) public class DemoApplication { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(DemoApplication.class, args); Access access = context.getBean(Access.class); access.start(); access.stop(); } } ``` ![file](https://img2018.cnblogs.com/blog/1747067/201909/1747067-20190910091130769-2137286790.jpg)
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!