Java使用@EnableEurekaServer实现自动装配详解

2022-11-13 java 装配 详解

实践

仿照@EnableEurekaServer实现自动装配

如果你使用过Eureka作为微服务的注册中心,那么对@EnableWebConfigure一定很了解,该注解用来开启Eureka服务端作为微服务的注册中心,其背后是SpringBoot自动装配原理。

本次,将仿照此设计思路,完成Web应用统一异常处理、TraceId链路日志追踪、JSON序列化消息处理器等通用能力的自动装配。

@EnableEurekaServer

通过源码我们得知,此注解的源码如下


@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(EurekaServerMarkerConfiguration.class)
public @interface EnableEurekaServer {
}

那么,如何通过在启动类标识此注解即可实现EurekaServer的自动装配呢?

答案其实在这一句

@Import(EurekaServerMarkerConfiguration.class)

该注解使用了@Import注解导入了一个配置类 EurekaServerMarkerConfiguration.java,该配置类源码如下

@Configuration(proxyBeanMethods = false)
public class EurekaServerMarkerConfiguration {
	@Bean
	public Marker eurekaServerMarkerBean() {
		return new Marker();
	}
	class Marker {
	}
}

我们看到,该配置类声明了一个Bean 内部类Marker

那么,为什么声明这个类?这个类看起来没有任何属性和方法

我们在导入的EurekaServer包中继续寻找答案

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

通过Command + 单击 Marker类,我们看到了如下引用

@ConditionalOnBean(EurekaServerMarkerConfiguration.Marker.class)

可以发现,一个条件装配使用了这个类,该注解的含义是当上下文中有Marker实例时,进行注解所在配置类的装配,也就是 EurekaServerAutoConfiguration

通过查看其源码,可以看到大量的EurekaServer相关Bean声明,也就是说,实现了EurekaServerAutoConfiguration的装配,也就实现类EurekaServer的装配

好的,思路清晰了 通过@EnableEurekaServer来导入EurekaServerMarkerConfiguration,进而将内部类Marker实例化到spring上下文中,通过条件装配,再来装配EurekaServerAutoConfiguration配置文件

也就是说 内部类Marker 起到了一个开关的作用

接下来只剩最后一个问题,我们只写了一行代码,也就是 @EnableEurekaServer 加到了springboot启动类上,那么 EurekaServerAutoConfiguration 是怎样被识别并导入到我们自己的项目中呢?

涉及到另一个知识点 spring.factories 它可以实现,将我们编写的jar包中的配置类,能够被依赖方识别到。

关于这点请自行百度查阅前置知识,只要理解它的作用,代码其实很简单。关于这点多说一下,许久之前我曾经有过疑惑,就是我编写的Common包其中包含了使用spring注解@Component、@Service、@Controller等修饰的Bean,那么引入这个jar包的spring工程,如何能够将

这个Bean注入到spring上下文中呢,使用@ComponentScan扫描,显然勉强能够实现,但是如果所有引入的工程都去改写@ComponentScan 显然不现实,spring.factories就可以灵活的实现该需求,自动的将配置进行导入

@EnableWebConfigure

@EnableWebConfigure 是我自定义的注解,期望用它来自动开启Web相关的公共能力,实现如下:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(WebMarkerConfiguration.class)
public @interface EnableWebConfigure {
}

注解标识在启动类上即可,它并没有属性和方法,仅导入了另一个配置类 WebMarkerConfiguration.class

@Configuration
public class WebMarkerConfiguration {
    @Bean
    public Marked createMarkedInstance(){
        return new Marked();
    }
    class Marked{
    }
}

可以看到,我很懒,连名字都跟EurekaServer中的实现一样…

而引用此Marked标识的是配置类 InternalCommonBeanConfiguration

@Configuration
@Import({WebConfig.class, WebmvcConfig.class})
@ConditionalOnBean(WebMarkerConfiguration.Marked.class)
public class InternalCommonBeanConfiguration {
    @Bean
    public GlobalExceptionInterceptor createGlobalExceptionInterceptor(){
        // 全局异常处理
        return new GlobalExceptionInterceptor();
    }
    @Bean
    public TransIdFilter createTransIdFilter(){
        // TraceId 过滤器
        return new TransIdFilter();
    }
}

类中除了声明GlobalExceptionInterceptor以及TransIdFilter,还导入了@Import({WebConfig.class, WebMvcConfig.class}) 这两个类用来配合@ResponseBody或者@RestController实现jsON序列化

最后,通过在internal-common工程resource文件下,新建 META-INF/spring.factories 文件,来暴露InternalCommonBeanConfiguration,以方便其他项目能够在依赖时,自动导入。

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  org.sun.online.internalcommon.configure.InternalCommonBeanConfiguration

具体工程中的应用请见 org.sun.online.serviceverificationcode.ServiceVerificationCodeApplication

设计价值

依赖方:后续的Web服务工程中,只需要@EnableWebConfigure 即可获得相应的通用能力

被依赖方:通过拓展 InternalCommonBeanConfiguration 即可令所有依赖方无需代码改动直接获得支持,方便升级维护

到此这篇关于Java使用@EnableEurekaServer实现自动装配详解的文章就介绍到这了,更多相关Java @EnableEurekaServer内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!

相关文章