SpringBoot手写 starter 及自定义配置参数---转

Starter是Spring Boot中的一个非常重要的概念,Starter 相当于模块,它能将模块所需的依赖整合起来并对模块内的Bean根据环境(条件)进行自动配置。使用者只需要依赖相应功能的Starter,无需做过多的配置和依赖,Spring Boot就能自动扫描并加载相应的模块。

比如我们在Maven的依赖中加入spring-bootstarter-web 就能使项目支持 Spring MVC,并且 Spring Boot 还为我们做了很多默认配置,无需再依赖 spring-web、 spring-webmvc 等相关包及做相关配置就能够立即使用起来。

SpringBoot 存在很多开箱即用的 Starter 依赖,使得我们 在开发业务代码时能够非常方便的、不需要过多关注框架的配置,而只需要关注业务即可。

问题一:starter命名规范?

spring官方:spring-boot-starter-{name}
自行提供:{name}-spring-boot-starter
问题二:starter中有什么?

比如下面是 mybatis-spring-boot-starter:
在这里插入图片描述

主要包含以下三部分:

基础jar包:引入了本来组件的jar包(mybatis.jar)及 jdbc的jar包
整合Spring的jar包:引入了与Spring整合的jar(mybatis-spring.jar)
自动装配的jar包:引入了具体自动创建相关bean的jar包(mybatis-spring-boot-autoconfigure.jar)
注:无需规定starter内jar包的具体版本,只用管大版本即可

OK,下面进入本篇的正文部分。假如现在我们要写一个能实现将对象转换为 String 或者 Json 的工具,并且暴露一个 HelloTemplate 对象去给用户调用。那我们该如何实现呢?

首先,我们来看如何实现这个组件。

1.组件基本实现
步骤一:首先得有一个统一的接口把,去规范要做的事情是转化对象

public interface FormatProcessor {
    // 定义一个格式化方法
    // 注:入参数一个object没什么说的,而处理结果中都是string类型(json也是String类型)
    <T>String format(T obj);
}

步骤二:下面我们要定义两个实现类:StringFormatProcessor ,JsonFormatProcessor

// 通过对象的toString()方法,直接将obj转化为String
public class JsonFormatProcessor implements FormatProcessor {
    @Override
    public <T> String format(T obj) {
        return "JsonFormatProcessor:" + JSON.toJSONString(obj);
    }
}

// 通过FastJson将obj转化为json字符串
public class StringFormatProcessor implements FormatProcessor{
    @Override
    public <T> String format(T obj) {
        return "StringFormatProcessor:" + Objects.toString(obj);
    }
}


步骤三:我们还需要创建一个 HelloTemplate 对象去供用户调用

public class HelloFormatTemplate {

    private FormatProcessor formatProcessor;
	
	// 根据构造 HelloTemplate 传入的对象,决定具体转化配普通string还是json串
    public HelloFormatTemplate(FormatProcessor formatProcessor) {
        this.formatProcessor = formatProcessor;
    }
	
	// 暴露的转化对象的方法
    public <T> String doFormat(T obj) {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("Execute format").append("\n");
        // 调用上面实现类的 format 方法进行转化
        stringBuilder.append("Obj format result: ").append(formatProcessor.format(obj)).append("\n");
        return stringBuilder.toString();
    }
}


好了,现在组件我们已经实现了,结构如下:

然后将组件 install 到本地,那用户该如何用调用这个组件呢?

=> 通过 new 进行外部调用

最简单的方式就是,在外部项目的 pom 文件中导入相应依赖坐标,然后直接 new HelloTemplate() 传入要转化的实现类。

@Test
public void f() {
	// new 出来 HelloTmeplate,并指定转化为 json
    HelloFormatTemplate helloFormatTemplate = new HelloFormatTemplate(new JsonFormatProcessor());
    String res = helloFormatTemplate.doFormat("hello starter");
    System.out.println(res);
}

问题:这里还是要将 HelloTemplate给 new出来,而我们希望的是直接@Autowired就直接使用了

既然要通过 @Autowired 直接获取对象使用,那势必该对象已经被初始化好并放到了 IOC 容器中。所以我们需要对上面的组件进行改造,目的是实现自动装配 HelloTemplate 对象。

2.组件改造,实现自动装配
步骤一:pom.xml 引入 spring-boot-starter相关注解

步骤二 :创建配置类,去定义我们要用到的 bean(三个)

  • FormatAutoConfiguration:定义 StringFormatProcessor 和 JsonFormatProcessor
  • HelloAutoConfiguration:定义 HelloTemplate
    @Configuration
    // 将具体工具类装载到Spring容器
    public class FormatAutoConfiguration { 
    
        @Bean
        @Primary // FormatProcessor有多个实现类时,要具体指定默认使用哪个
        @ConditionalOnMissingClass("com.alibaba.fastjson.JSON") // 当没有fastjson时注入StringFormat
        public FormatProcessor stringFormat() {        			// 注:这里是以核心类代替整个组
            return new StringFormatProcessor();        			//比如我们判断如果有redis时,是拿使用redis的核心类
        }
    
        @Bean
        @ConditionalOnClass(name = "com.alibaba.fastjson.JSON") // 当存在fastjson时注入JsonFormat
        public FormatProcessor jsonFormat() {
            return new JsonFormatProcessor();
        }
    }
    
    @Configuration
    @Import(FormatAutoConfiguration.class) // 将具体FormatProcess的Bean扫描进来(@ComponentScan 可以替换@Import,但一般不这么做)
    // 将对外HelloTemplate交给Spring容器
    public class HelloAutoConfiguration { 
    
        @Bean
        // 由于import了Format这Bean的配置类,spring就有据可依的能找到相应bean作为入参
        // 这里还会根据具体Condition判断注入哪个bean
        public HelloFormatTemplate helloFormatTemplate(FormatProcessor formatProcessor) {
            return new HelloFormatTemplate(formatProcessor);
        }
    }
    

    现在这个配置类是写好了,但是如何让 Spring 将它加载进来呢?(因为加载后就会将里面配置的bean放到IOC容器中)
    根据我们上一篇 【SpringBoot】原理分析(一):自动装配原理分析,我们知道 SpringBoot 能实现自动装配的核心就是实现了类似 SPI 的加载机制,可以动态装载 spring.factories 中配置的bean。

 步骤三:创建 spring.factories 将要加载的类配置进去

#  spring.factories
# key是EnableAutoConfiguration注解
# 作用:类似于Bean扫描,让Spring动态加载这些类,并且这动态加载时还可再进行判断筛选
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.xupt.starter.autoConfiguration.FormatAutoConfiguration,\
  com.xupt.starter.autoConfiguration.HelloAutoConfiguration

此时项目结构如下:

=> 通过 @Autowired 进行外部调用

 问题:上面的自动装配算是完了,但是我们可不可以也在 application.properties 定义属性,然后读取到 HelloTemplate 中。

3.改造组件,实现自定义属性

可以实现用户设置property,实质上是读取有用的property

步骤一:编写 HelloProperties 去读取我们在 application.properties 中的配置

@ConfigurationProperties(prefix = HelloProperties.HELLO_FORMAT_PREFIX) // 标识这是个读取属性类
public class HelloProperties {                        				   // 注:设置属性与读取属性是因果关系
                                                                       // 即配置文件中设置什么都可以,但读不出就不一定
	// 要配置属性到前缀名
    public static final String HELLO_FORMAT_PREFIX = "hello.format";
    // 要配置属性的类型
    private Map<String, String> info;
	
    // getter,setter是必须的
    public Map<String, String> getInfo() {
        return info;
    }
    public void setInfo(Map<String, String> info) {
        this.info = info;
    }
}

步骤二:改造 helloFormatTemplate 的 doFormat 方法,使用读入的参数(将参数打印出来)

 步骤三:改造 HelloAutoConfiguration,构造HelloTemplate时注入配置内容

@Configuration
@Import(FormatAutoConfiguration.class) // 将具体FormatProcessor的Bean扫描进来
@EnableConfigurationProperties(HelloProperties.class) // 将具体属性Bean(HelloProperties)扫描进来
public class HelloAutoConfiguration {                 // 注:这不是要加入IOC的Bean,所以不能用Componet替换

    @Bean
    // 将扫描进来的FormatProcessor与属性Bean注入到HelloTemplate
    public HelloFormatTemplate helloFormatTemplate(FormatProcessor formatProcessor, HelloProperties helloProperties) {
        return new HelloFormatTemplate(formatProcessor, helloProperties);
    }
}

=> 通过 application.properties 读取自定义参数

具体调用代码不变结果如下:

完整代码我放到 GitHub 上了,点击这里跳转…

-----------------------

原文链接:【SpringBoot】手写 starter 及自定义配置参数_spring starter 注入_A minor的博客-CSDN博客 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当然可以!以下是一个简单的示例,展示了如何手写一个Spring Boot Starter: 首先,创建一个 Maven 项目,并添加以下依赖项: ```xml <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <version>2.5.4</version> </dependency> </dependencies> ``` 接下来,创建一个自定义的自动配置类,用于配置你的 Starter: ```java @Configuration @EnableConfigurationProperties(MyStarterProperties.class) public class MyStarterAutoConfiguration { private final MyStarterProperties properties; public MyStarterAutoConfiguration(MyStarterProperties properties) { this.properties = properties; } // 在此处定义你的自动配置逻辑 @Bean public MyStarterService myStarterService() { return new MyStarterService(properties); } } ``` 然后,创建一个属性类,用于将外部配置绑定到属性上: ```java @ConfigurationProperties("my.starter") public class MyStarterProperties { private String message; // 提供 getter 和 setter } ``` 最后,创建一个自定义的服务类,该服务类将在你的 Starter 中使用: ```java public class MyStarterService { private final MyStarterProperties properties; public MyStarterService(MyStarterProperties properties) { this.properties = properties; } public void showMessage() { System.out.println(properties.getMessage()); } } ``` 现在,你的 Spring Boot Starter 已经准备就绪了!你可以将其打包并使用在其他 Spring Boot 项目中。在其他项目的 `pom.xml` 文件中,添加你的 Starter 依赖: ```xml <dependencies> <dependency> <groupId>com.example</groupId> <artifactId>my-starter</artifactId> <version>1.0.0</version> </dependency> </dependencies> ``` 然后,在你的应用程序中使用 `MyStarterService`: ```java @SpringBootApplication public class MyApplication implements CommandLineRunner { private final MyStarterService myStarterService; public MyApplication(MyStarterService myStarterService) { this.myStarterService = myStarterService; } public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); } @Override public void run(String... args) throws Exception { myStarterService.showMessage(); } } ``` 这样,你就成功地创建了一个简单的 Spring Boot Starter!当其他项目引入你的 Starter 并运行时,将会输出预定义的消息。 当然,这只是一个简单的示例,真实的 Starter 可能包含更多的配置和功能。你可以根据自己的需求进行扩展和定制。希望对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值