Java使用@EnableEurekaServer实现自动装配详解
作者:hongmin.shm 发布时间:2023-08-23 19:50:32
实践
仿照@EnableEurekaServer实现自动装配
如果你使用过Eureka作为微服务的注册中心,那么对@EnableWebConfigure一定很了解,该注解用来开启Eureka服务端作为微服务的注册中心,其背后是springboot自动装配原理。
本次,将仿照此设计思路,完成Web应用统一异常处理、TraceId链路日志追踪、Json序列化消息处理器等通用能力的自动装配。
@EnableEurekaServer
通过源码我们得知,此注解的源码如下
/**
* Annotation to activate Eureka Server related configuration.
* {@link EurekaServerAutoConfiguration}
*
* @author Dave Syer
* @author Biju Kunjummen
*
*/
@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
即可令所有依赖方无需代码改动直接获得支持,方便升级维护
来源:https://blog.csdn.net/qq_41788977/article/details/125120962


猜你喜欢
- 本文实例讲述了Android编程自定义对话框(Dialog)位置及大小的方法。分享给大家供大家参考,具体如下:代码:package ange
- 人机交互过程中,当我们需要机器给我们反馈不确定的数字结果时,就会需要用到随机数了,那么,在Java中,我们应当如何来生成并使用随机数呢?一、
- 本文实例讲述了C#中list用法。分享给大家供大家参考,具体如下:protected void Page_Load(object sende
- 本文较为详细的分析了Java中对象的销毁方法。分享给大家供大家参考。具体分析如下:Java中的基本数据类型变量和对象的名称引用变量如定义在方
- 代码注释是架起程序设计者与程序阅读者之间的通信桥梁,最大限度的提高团队开发合作效率。也是程序代码可维护性的重要环节之一。所以我们不是为写注释
- ${} 和 #{} 都是 MyBatis 中用来替换参数的,它们都可以将用户传递过来的参数,替换到 MyBatis 最终生成的 SQL 中,
- 1. 将对象转换为JSON字符串,返回值为一个JSON字符串public static String toJson(Object value
- using System;using System.Collections.Generic;using System.Linq;using
- Android上使调用OpenCV 2.4.10 实现二维码区域定位(Z-xing 码),该文章主要用于笔者自己学习中的总结,暂贴出代码部分
- Mybatis基础回顾与高级应用数据库:mysql5.7jdk:15引入依赖<!--引入依赖--> &
- 一、稀疏数组1、什么是稀疏数组当一个数组中大部分元素为0,或者为同一个值的数组时,可以用稀疏数组来保存该数组。稀疏数组,记录一共有几行几列,
- 包括了写入和读取功能. 写入的时候, 如果文件不存在会自动创建. 如果对应的键已经存在, 则自动覆盖它的值. 读取的时候, 如果对应的文件不
- 前言最近看了内部类后,总结一下,首先内部类嵌套在其他内部的类,根据出现的位置和关键字,可以分为以下四种类:成员内部类,静态内部类,方法内部类
- Pull解析方法给应用程序完全的控制文档该怎么样被解析。Android中对Pull方法提供了支持的API,主要是org.xmlpull.v1
- 之前文章介绍过了Fluent基本框架等,其中有几个重要的方法用到了IQuery和IUpdate对象。 这2个对象是FluentMybatis
- 废话不多说了,直接给大家贴代码了,具体代码如下所示:package wxapi.WxHelper; import java.io.Buffe
- 步骤,如图所示:1.添加异步任务业务类package top.ytheng.demo.task;import java.util.concu
- maven使用exec插件运行java main方法,以下是3种不同的操作方式。一、从命令行运行1、运行前先编译代码,exec:java不会
- Java动态数组Arraylist存放自定义数据类型class Point{ int x; int y; public Point(int
- 本文实例讲述了C#采用OpenXml实现给word文档添加文字的方法,分享给大家供大家参考。具体方法如下:一般来说,使用OpenXml给wo