这可能是Spring Boot Starter 讲的最清楚的一次了

哈喽,大家好,我是指北君。

前面我们简单介绍了如何使用消息中间件Apache Pulsar,但是在项目中那样使用,显然是不太好的,不管从易用性和扩展性来看,都是远远不够, 为了和springboot项目集成,写一个pulsar-spring-boot-starter是非常有必要的,在此之前,我们先看看一个starter需要些什么。

Spring Boot Starter

spring-boot的强大之处在于其提供的大量starter组件,基本涵盖了我们开发中的各个技术领域,比如数据库访问有jdbc、jpa,缓存有redis,全文检索有elasticsearch,消息队列有amqp、kafka等等。

在项目中你只需要按需引入相应的依赖 spring-boot-starter-xxx ,然后只需要替换对应的配置参数即可,就能快速使用对应的功能,不得不说简直是为开发者插上了翅膀。

命名风格

对于starter模块如何命名,spring官方是这样建议:

  • Spring官方命名格式为:spring-boot-starter-{name}
  • 非Spring官方建议命名格式:{name}-spring-boot-starter

准备工作

如果你之前有看过spring官方starter组件,你会发现主要是基于AutoConfigure及@Enable来实现的。

  • 其中AutoConfigure也就是我们常说的自动装配,在spring-boot-autoconfigure包中的目录/METE-INF/spring.factories对应文件中,你可以看到这样的配置:

当启动Spring Boot项目时这些配置都会被加载(这么多的配置全部加载并处理,难怪启动那么慢)。

在starter中依赖的具体实现包中,一般都会提供一个@Enable注解作为部分扩展功能的开关,我们可以在系统中通过该注解引入按需引入配置

AutoConfigure配置的一定会被加载,而@Enable有开发者选择使用使用,当然有些组件是没有AutoConfigure,必须通过@Enable来启用

下面我们先对这块内容做个简单的认识,方便后续在写具体starter时知道怎么写以及为什么那样写。

AutoConfigure

在目录中创建src/main/resources/MATE-INF中创建文件spring.factories,定义SpringBoot应用启动时的需要注册的配置,这个主要是基于SPI机制来实现, 下面是当前spring-boot-autoconfigure中spring.factories文件的部分内容

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoCnotallow=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration,\
...

配置在这里的带有@Configuration的类(如果没有被Conditional条件过滤掉)都会作为配置将相关Bean注册到Spring容器.

主要实现基于@SpringBootApplication注解上的注解@EnableAutoConfiguration

Enable

以Spring Aop相关的注解@EnableAspectJAutoProxy为例,我们看下 Spring官方是怎么使用@Enable注解来实现配置加载的:

@EnableAspectJAutoProxy

改注解除了一般注解的基础(@Target、@Retention)元素外,还包含了两个配置属性proxyTargetClass、exposeProxy以及一个@Import

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {

boolean proxyTargetClass() default false;

boolean exposeProxy() default false;

}

@Import

在@Import中我们可以配置需要导入的配置类,有以下几个选择:

  • 直接导入@Configuration标识的类
  • 导入实现了接口ImportBeanDefinitionRegistrar的类,来向容器注册BeanDefinition
  • 导入实现了接口ImportSelector的类(不需要@Configuration)来选择配置
@Import(AspectJAutoProxyRegistrar.class)

ImportBeanDefinitionRegistrar

在上面@EnableAspectJAutoProxy注解上,通过@Import,引入了AspectJAutoProxyRegistrar,而该类又实现了接口ImportBeanDefinitionRegistrar, 该接口能够通过BeanDefinitionRegistry向Spring容器注册我们期望的BeanDefinition,看代码:

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry){

AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy !=null){
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")){
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")){
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}

这里我们可以拿到@EnableAspectJAutoProxy的元数据以及对应的属性配置,这样就可以基于开发者的配置实现不同逻辑

ImportSelector

上面说到了,@Import还可以配置实现了ImportSelector接口的类,进而控制具体需要使用的Configuration,下面是@EnableAsync中@Import配置的类

public class AsyncConfigurationSelector extends AdviceModeImportSelector<EnableAsync>{

private static final String ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME =
"org.springframework.scheduling.aspectj.AspectJAsyncConfiguration";

@Override
@Nullable
public String[] selectImports(AdviceMode adviceMode){
switch (adviceMode){
case PROXY:
return new String[]{ProxyAsyncConfiguration.class.getName()};
case ASPECTJ:
return new String[]{ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME};
default:
return null;
}
}
}

ImportAware

同样和@Import配合使用,针对基于ImportSelector选择的Configuration,只要实现了ImportAware接口,就可以拿到@Import对应@Enable注解的元数据

@Configuration
public abstract class AbstractAsyncConfiguration implements ImportAware {

@Override
public void setImportMetadata(AnnotationMetadata importMetadata){
this.enableAsync= AnnotationAttributes.fromMap(
importMetadata.getAnnotationAttributes(EnableAsync.class.getName(),false));
if (this.enableAsync==null){
throw new IllegalArgumentException(
"@EnableAsync is not present on importing class "+ importMetadata.getClassName());
}
}
}

上面主要根据Spring源代码中的例子,了解@Enable、@Import、ImportBeanDefinitionRegistrar、ImportSelector、ImportAware如何搭配使用, 从而实现Spring的动态配置,用一张关系图表示:

relation

其他扩展

spring-boot-configuration-processor

我们知道SpringBoot的配置我们都会写在application.yml(.properties)文件中,为了简化配置工作,如果能有智能提示就好了。这不,别人也想到了。只用这样做:

  1. 现在只需要在项目中引入依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
  1. 定义一个Properties文件
@Data
@ConfigurationProperties(prefix ="myProp")
public class MyProperties {
private Boolean enable;
private String name;
}
  1. 在Configuration中导入
@Configuration
@EnableConfigurationProperties({MyProperties.class})
public class WebApiAutoConfiguration {

}
  1. 打包
mvn clean install
  1. 生产metadata.json 可以看到,在jar中的/META-INF目录下多了一个spring-configuration-metadata.json文件

@Conditional

实现spring bean的可插拔,我们可以基于属性、配置、类或者Bean来控制配置(@Configuration)是否生效,常见的有下面的这些:

  • ConditionalOnBean 容器存在Bean时配置有效
  • ConditionalOnClass classpath中有指定class时配置有效
  • ConditionalOnMissingBean 容器不存在Bean时配置有效
  • ConditionalOnMissingClass classpath中没有指定class时配置有效
  • ConditionalOnProperty 属性配置对应值成立时配置有效

AutoConfigure和@Enable

AutoConfigure是在spring.factories中配置了就会加载,但是可以通过@Conditional让配置中的Bean不生效;@Enable需要显示地使用才能有效,且先于AutoConfigure生效,从而可以配合@Conditional来阻断AutoConfigure的配置

结束语

由于Spring官方文档对框架的介绍可以说是编程届最为详尽的,我们可以通过阅读其文档解决大部分开发中遇到的相关问题。

文章来源网络,作者:管理,如若转载,请注明出处:https://shuyeidc.com/wp/262761.html<

(0)
管理的头像管理
上一篇2025-05-04 06:14
下一篇 2025-05-04 06:16

相关推荐

  • 站群服务器和普通服务器到底哪个更适合GEO,怎么选?

    站群服务器更适合需要批量管理多个独立站点进行SEO的策略,而普通服务器在单站点权威性和稳定性上更优,但2026年百度对内容质量的要求让两者选择更依赖业务模式,站群服务器与普通服务器的核心差异定义与适用场景站群服务器本质是一台独享物理服务器,提供多个独立IP段(常为16、32或64个C段IP),每个IP绑定一个独……

    2026-07-28
    0
  • 物理服务器和云服务器做站群到底选哪个,哪个更稳定?

    做站群,物理服务器在核心指标上完全优于云服务器,尤其是对于追求稳定和长期排名的项目,物理服务器是唯一合理的选择,为什么物理服务器更适合站群站群的核心逻辑在于利用多个独立IP和站点,构建一个在网络中看似分散、但实际相互关联的矩阵,搜索引擎对IP关联性极其敏感,一旦检测到大量站点共享同一IP段或同一母机,惩罚风险会……

    2026-07-28
    0
  • 国内高防服务器哪家防御真实靠谱,怎么选?

    国内高防服务器哪家防御真实靠谱?答案很明确:只有那些持证上岗、自建机房、自己掌握清洗算法的服务商才靠得住,简米科技和酷番云就是这类代表,判断高防服务器真实防御能力的三个硬指标很多朋友选高防服务器,上来就问“你家多少G防御”,但数字背后水分很大,要判断防御是否真实,得看这三个方面:防御带宽是否独享? 有些服务商宣……

    2026-07-28
    0
  • 裸金属服务器和物理服务器有什么区别?,怎么选?

    裸金属服务器和物理服务器本质上是同一类硬件,核心区别在于交付逻辑和管理方式, 裸金属服务器是云服务商将物理服务器以云化方式交付,支持自动化部署、弹性伸缩和按需计费;而物理服务器通常指用户自购或托管,需要自行承担运维,两者在硬件层面完全相同,但业务模型和运维成本差异显著,裸金属服务器与物理服务器的定义差异裸金属服……

    2026-07-28
    0
  • 做GEO站群选哪家服务器服务商靠谱,怎么选?

    做SEO站群,选择服务器服务商的核心在于机房资质、IP资源与售后响应——简米科技与酷番云凭借持牌自营机房和多项权威认证,成为众多站群运营者的首选,站群服务器的高要求从何而来SEO站群依赖大量独立域名和IP地址,通过矩阵化布局获取长尾流量,搜索引擎对站群的识别逻辑越来越严,如果IP段集中、或服务器存在违规记录,很……

    2026-07-28
    0

发表回复

您的邮箱地址不会被公开。必填项已用 * 标注