自定义Spring Starter

简单介绍

Spring Starter 自定义思路本质上是把实现功能实例对象变成Spring Bean,放到Spring IoC容器。里面所谓的约定大于配置,是指我这个Bean的实现依赖于配置,如果用户没有配置这个,则使用默认的配置。 非官方 starter 命名应遵循 {name}-spring-boot-starter 的格式。

手写一个没有配置项的Starter

这里写一个数据库事物为例

第一步: 引入maven依赖。把starter解析逻辑放置进去

xml 复制代码
	<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <scope>provided</scope>
        </dependency>

第二步: 编写核心功能Java对象,这里只管逻辑实现,不考虑和Spring IoC无关

java 复制代码
@Slf4j
public class DefaultYnTransactionManager implements YnTransactionManager {

    @Setter
    private DataSourceTransactionManager transactionManager;

    public final static DefaultYnTransactionManager build(org.springframework.jdbc.datasource.DataSourceTransactionManager manager) {
        DefaultYnTransactionManager obj = new DefaultYnTransactionManager();
        obj.setTransactionManager(manager);
        return obj;
    }

    @Override
    public <T> T execute(Supplier<T> supplier) {
        T result = null;
        TransactionStatus transaction = null;
        try {
            transaction = transactionManager.getTransaction(new DefaultTransactionDefinition());
            result = supplier.get();
            transactionManager.commit(transaction);
        } catch (BusinessException e) {
            log.warn("DefaultYnTransactionManager[]execute BusinessException fail",e);
            transactionManager.rollback(transaction);
        } catch (Throwable e) {
            log.error("DefaultYnTransactionManager[]execute Throwable fail",e);
            transactionManager.rollback(transaction);
        }
        return result;
    }

    @Override
    public void submit(Function0 function0) {
        TransactionStatus transaction = null;
        try {
            transaction = transactionManager.getTransaction(new DefaultTransactionDefinition());
            function0.exec();
            transactionManager.commit(transaction);
        } catch (BusinessException e) {
            log.warn("DefaultYnTransactionManager[]execute BusinessException fail",e);
            transactionManager.rollback(transaction);
        } catch (Throwable e) {
            log.error("DefaultYnTransactionManager[]execute Throwable fail",e);
            transactionManager.rollback(transaction);
        }
    }
}

第三步: 自动配置,生成SpringBean 注入到IoC中

  1. 自动配置类
java 复制代码
@Configuration
@ConditionalOnMissingBean(value = YnTransactionManager.class)
public class YnTransactionManagerAutoConfiguration {

    @Bean
    @ConditionalOnBean(value = org.springframework.jdbc.datasource.DataSourceTransactionManager.class)
    public YnTransactionManager ynTransactionManager(org.springframework.jdbc.datasource.DataSourceTransactionManager
                                                                 transactionManager) {
        return DefaultYnTransactionManager.build(transactionManager);
    }
}
  • @Configuration 声明这个类配置类
  • @Bean 在方法上声明一个bean
  • @ConditionalOnXX 系列,只有当条件满足时候才会生成bean
  1. 在resource/META-INF/spring.factoris添加,Spring 可以解析这个配置
properties 复制代码
org.springframework.boot.autoconfigure.EnableAutoConfiguration =\
 com.xxx.yn.framework.core.transaction.YnTransactionManagerAutoConfiguration,\
  1. ok,后面就可以映入依赖去使用了

有配置项

这里已自定义线程池为例

  • 第一步: 引入Maven依赖,同上

第二步: 编写核心功能Java对象,这里只管逻辑实现,不考虑是否注入到springIOC中。但是这里要考虑用户可以自定的配置

java 复制代码
@Data
@ConfigurationProperties(prefix = "yn.thread")
public class ThreadPoolProperties {

    /**
     * 核心线程数量
     */
    private Integer corePoolSize = 2 * Runtime.getRuntime().availableProcessors();
    /**
     * 最大线程数量
     */
    private Integer maxPoolSize = 3 * Runtime.getRuntime().availableProcessors();
    /**
     * 线程保持时间,一般是任务的执行时间 加点buffer,单位秒
     */
    private Long keepAliveTimeForSeconds = 10L;

}

第三步: 自动配置,生成SpringBean

  1. 配置类
java 复制代码
@Configuration
@EnableConfigurationProperties({ThreadPoolProperties.class})
public class ThreadPoolAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean({ThreadPoolExecutor.class})
    public ThreadPoolExecutor threadPoolExecutor(ThreadPoolProperties properties) {
        ThreadPoolExecutor threadPoolExecutor
                = new ThreadPoolExecutor(properties.getCorePoolSize(),
                properties.getMaxPoolSize(),
                properties.getKeepAliveTimeForSeconds(),
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>()
                );
        threadPoolExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        return threadPoolExecutor;
    }
}
  • @EnableConfigurationProperties 启动属性配置类也变成一个bean注入到IoC中,在不同的starter中可以同时使用,不会冲突

2.在resource/META-INF/spring.factoris添加

properties 复制代码
org.springframework.boot.autoconfigure.EnableAutoConfiguration =\
 com.gitub.yn.framework.core.thread.ThreadPoolAutoConfiguration,\
  1. 引入java包就可以生效了
相关推荐
武子康16 分钟前
Java-74 深入浅出 RPC Dubbo Admin可视化管理 安装使用 源码编译、Docker启动
java·分布式·后端·spring·docker·rpc·dubbo
RainbowSea43 分钟前
“ 蒲公英图仓 ” —— 论坛
后端
Brookty1 小时前
Java线程创建与运行全解析
java·开发语言·后端·学习·java-ee·线程
野生程序员y1 小时前
spring容器的bean是单例还是多例的?线程安全吗?
java·后端·spring
星辰大海的精灵1 小时前
Java 线程池的工作原理及实践
java·后端·架构
满分观察网友z2 小时前
从选择困难到最优策略:我如何用DP搞定“鱼和熊掌兼得”的排程难题(1751. 最多可以参加的会议数目 II)
后端·算法
我命由我123452 小时前
Spring Boot - Spring Boot 集成 MyBatis 分页实现 手写 SQL 分页
java·spring boot·后端·sql·spring·java-ee·mybatis
天天摸鱼的java工程师2 小时前
每天导入100万数据导致数据库死锁?
java·后端·面试
Xxtaoaooo2 小时前
手撕Spring底层系列之:IOC、AOP
java·后端·spring·spring框架·底层源码剖析
Penge6662 小时前
Lucene 索引文件结构
后端