美文网首页
自定义spring boot starter

自定义spring boot starter

作者: 非典型_程序员 | 来源:发表于2019-09-14 11:01 被阅读0次

前段时间在面试的过程中遇到面试官的一个问题,怎么自己定义一个spring boot的starter,当时其实自己是有点懵的,说实话以前真的没有注意过这个问题,不过好在自己看过一些具体的starter依赖,然后大概回答了一下。然后趁着周末决定来看一下到底是怎么一回事。
在spring boot项目中我们经常会使用到各种starter,比如spring-boot-starter-webspring-boot-starter-data-jpa等等,其实如果你深入的跟踪过这些pom.xml的话你会发现,其实这些所谓的starter不过是一个依赖的集合而已,可以理解为对所需要的依赖进行了一层包装。这样的好处就是相对更加灵活一些,每一个starter可以看作是一个组件,这个组件包了相关的依赖,以spring-boot-starter-web为例,我们看下它的组成到底是怎么样的:

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
      <version>2.1.8.RELEASE</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-json</artifactId>
      <version>2.1.8.RELEASE</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-tomcat</artifactId>
      <version>2.1.8.RELEASE</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.hibernate.validator</groupId>
      <artifactId>hibernate-validator</artifactId>
      <version>6.0.17.Final</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>5.1.9.RELEASE</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.1.9.RELEASE</version>
      <scope>compile</scope>
    </dependency>
  </dependencies>

根据上面的依赖可以知道,其实它也不过是引用了一些其他相关的依赖而已,它只是将这些依赖集中起来而已。比如有spring-webmvc、有spring-boot-starter-tomcat(你可以接着向下看它的组成)。这样它就做成了一个组件,不管是引用还是移除我们只需要关心它就行了。

一、自定义一个starter

根据上面的这些如果我们想自定义一个starter我们应该怎么做呢?在工作中我也在项目中使用过我们公司自己定义的一些starter,比如ES、redis等等。接下来尝试自己定义一个很简单的starter

1、创建一个maven项目

使用IDE创建一个maven工程,然后定义好相关的 groupIdartifactIdversion,然后在pom文件引入相关的依赖,主要是spring boot自动配置相关的依赖,pom.xm文件依赖如下:

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-autoconfigure</artifactId>
      <version>2.1.8.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-configuration-processor</artifactId>
      <version>2.1.8.RELEASE</version>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.7.25</version>
    </dependency>
  </dependencies>

然后我们需要定义一个配置类ServiceConfigProperties,其实如果不会的话参考一下其他的starter,代码如下:

@ConfigurationProperties(prefix = "com.ypc.service")
public class ServiceConfigProperties {

    private String name = "starter";

    private String url = "localhost";

    private String username;

    private String password;

    private Integer count = 1;

    // 省略get set
    ......
}

然后我们需要定义一个自动配置类ServiceAutoConfiguration,这个自动配置的作用就是对外提供一个或多个相关的bean,以便可以直接注入到spring容器中。比如RedisAutoConfiguration会创建RedisTemplateStringRedisTemplate两个bean。所以我们也需要创建一个具体的服务类(这个根据具体的starter决定)StarterService,这个类本身在这里并不具备很具体的功能,仅仅是作为一个例子,代码如下:

public class StarterService {

    private String serviceName;

    private String url;

    private String password;

    private Integer count;

    public StarterService() {
    }

    public StarterService(String serviceName, String url, String password, Integer count) {
        this.serviceName = serviceName;
        this.url = url;
        this.password = password;
        this.count = count;
    }
    
    // 省略get set方法
    .......
}

最后就是自动配置类的代码,这个配置我们需要spring boot能自动进行配置,代码如下:

@Configuration
@EnableConfigurationProperties(ServiceConfigProperties.class)
public class ServiceAutoConfiguration {

    private static final Logger LOGGER = LoggerFactory.getLogger(ServiceAutoConfiguration.class);

    @Autowired
    private ServiceConfigProperties serviceConfigProperties;

    @Bean("starterService")
    public StarterService starterService() {
        LOGGER.info(">>>> starter service start <<<<");
        StarterService starterService = new StarterService();

        starterService.setCount(serviceConfigProperties.getCount());
        starterService.setUrl(serviceConfigProperties.getUrl());
        starterService.setPassword(serviceConfigProperties.getPassword());
        starterService.setServiceName(serviceConfigProperties.getName());

        return starterService;
    }
}

需要注意一点就是在该类上使用@EnableAutoConfiguration注解并不能让spring去注入我们创建的bean。一开始我只是添加了@EnableAutoConfiguration,但是在引入到项目中启动时报错,显示无法注入自定义的bean——StarterService。后来网上找了下相关资料发现需要在resources目录下创建名为META-INF文件夹,并新建一个文件spring.factories,然后添加下面的内容:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.ypc.springboot.starter.ServiceAutoConfiguration

详情可以参考Spring-boot @EnableAutoConfiguration源码分析

2、在其他项目中使用starter

然后我们需要将项目打包,并安装到我们本地的maven仓库,执行下面的maven命令:

mvn clean install

或者直接使用maven插件进行也可以。
接下来我们需要新创建一个spring boot的项目,并在该项目中引入自定义的starter,我的依赖如下:

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- 引入自定义的service starter -->
        <dependency>
            <groupId>com.ypc.springboot.custom</groupId>
            <artifactId>service-starter</artifactId>
            <version>1.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

然后在application.properties配置自定义starter配置类的相关内容,如下:

图-1.png
编写一个简单的接口,并在相应代码中注入依赖使用的bean——StarterService,然后调用一个方法即可,代码如下:
@Slf4j
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private StarterService starterService;

    @Override
    public UserEntity queryByUserName(String userName) {
        String result = starterService.hello();
        log.info(">>>> starter service hello={} <<<<",result);

        UserEntity userEntity = userRepository.findByUserName(userName);
        return userEntity;
    }
}

看下日志输出如下:

图-2.png
说明自定义的starter在项目中是可以正常使用的,当然这个例子有点过于简单了,也并没有什么实际的价值,只是提供了一种自定义starter的思路。如果在实际开发中需要自定义starter其实参考spring boot提供那些starter就可以了。

相关文章

网友评论

      本文标题:自定义spring boot starter

      本文链接:https://www.haomeiwen.com/subject/abieyctx.html