(六)SpringBoot的启动入口main方法以及自定义starter

技术/杨33

一、SpringBoot做的自动配置确实方便快捷,执行下面这个启动类,就可以加载完成项目的所有依赖组件。

<code>package com.test.demo.springbootdemo01;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringbootDemo01Application {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootDemo01Application.class, args);
    }
}/<code>

项目中的其他包必须与此类在同级目录或者子包下 ,否则扫描不到。

(六)SpringBoot的启动入口main方法以及自定义starter

项目中的其他包必须与此类在同级目录或者子包下

二、只有一个注解@SpringBootApplication和一个run方法是怎么实现自动配置的?

分别说一下这两个的原理到底是什么?

1、注解@SpringBootApplication

  • 打开@SpringBootApplication源码

看到重要的三个注解@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan

(六)SpringBoot的启动入口main方法以及自定义starter

@SpringBootApplication源码

  • 注解@SpringBootConfiguration的源码又是@Configuration

标注了@Configuration,那么它就是一个Spring IOC容器的基于JavaConfig的配置类。

标注了@Bean,那么方法的返回值作为一个bean注册到Spring IOC容器中,方法名getHelloService()对应ioc容器的id。

对比下Java代码和XML配置分别实现注册bean

下面代码是基于JavaConfig的配置类实现注册bean,以及bean与bean之间的依赖关系

<code>package com.test.demo.springbootdemo01.config;

import com.test.demo.springbootdemo01.service.HelloService;
import com.test.demo.springbootdemo01.service.UserService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author yang33
 * @date 2020/4/18 23:06
 */
@Configuration
public class BootConfig {
    /**
     * 将HelloService组件添加到容器中,方法名getHelloService()对应ioc容器的id
     */
    @Bean
    public HelloService getHelloService() {
        return new HelloServiceImpl(userService());
    }

    @Bean
    public UserService userService() {
        return new UserServiceImpl();
    }
}/<code>

下面代码是基于XML文件的配置实现注册bean,以及bean与bean之间的依赖关系

<code>


    
        
    
    

    
/<code>
  • 注解@ComponentScan的功能

其实就是自动扫描加载符合条件的组件(比如@Component和@Repository等)或者bean定义,最终将这些bean定义加载到Spring IOC容器中。

我们可以通过basePackages等属性来细粒度的定制@ComponentScan自动扫描的范围,如果不指定,则默认Spring框架实现会从声明@ComponentScan所在类的package进行扫描。

所以SpringBoot的启动类最好是放在root package下,因为默认不指定basePackages。

  • 注解@EnableAutoConfiguration的功能
  • (六)SpringBoot的启动入口main方法以及自定义starter

    里面最关键的是@Import({AutoConfigurationImportSelector.class}),借助AutoConfigurationImportSelector,@EnableAutoConfiguration可以帮助SpringBoot应用将所有符合条件的@Configuration配置都加载到当前SpringBoot创建并使用的Spring IOC容器。

    2、run方法

    执行run方法,做了两件事。

    第一,创建SpringApplication对象,new SpringApplication(primarySources);

    第二,运行run方法,run(args)。

    <code>public static ConfigurableApplicationContext run(Class>[] primarySources, String[] args) {
            return (new SpringApplication(primarySources)).run(args);
    }/<code>

    三、SpringBoot自定义启动器starter

    启动器只用来做依赖导入,专门写一个自动配置模块。启动器依赖自动配置,使用时只需要引入启动器(starter)。

    启动器就是个空jar文件,仅提供辅助性依赖管理,这些依赖可能用于自动装配或者其他库。

    1、启动器starter命名规范

    • 自定义命名规范

    模块名-spring-boot-starter

    • 官方命名规范

    spring-boot-starter-模块

    2、配置自定义启动器需要两个项目

    他俩的关系是启动器依赖自动配置。

    • xxx-starter,别的项目引用,只需引入该启动器即可,提供辅助性依赖管理。
    • xxx-autoconfigure,自动配置,给启动器提供依赖。

    3、IDEA工具创建项目

    • 先创建启动器starter项目 demostarters
    (六)SpringBoot的启动入口main方法以及自定义starter

    步骤1

    (六)SpringBoot的启动入口main方法以及自定义starter

    步骤2

    (六)SpringBoot的启动入口main方法以及自定义starter

    步骤3

    (六)SpringBoot的启动入口main方法以及自定义starter

    步骤5

    (六)SpringBoot的启动入口main方法以及自定义starter

    步骤6

    (六)SpringBoot的启动入口main方法以及自定义starter

    步骤7

    • 在创建一个自动配置的项目 demo-spring-boot-starter-autoconfigure
    (六)SpringBoot的启动入口main方法以及自定义starter

    步骤1

    (六)SpringBoot的启动入口main方法以及自定义starter

    步骤2

    (六)SpringBoot的启动入口main方法以及自定义starter

    步骤3

    (六)SpringBoot的启动入口main方法以及自定义starter

    步骤5

    (六)SpringBoot的启动入口main方法以及自定义starter

    步骤6

    最终创建的两个项目:启动器项目和自动配置项目,如图:

    (六)SpringBoot的启动入口main方法以及自定义starter

    启动器项目和自动配置项目

    4、代码实现两个项目

    • 启动器依赖自动配置,在启动器项目的pom.xml文件中添加自动配置项目的依赖
    <code> 
    
          com.demo.starters
          demo-spring-boot-starter-autoconfigure
          0.0.1-SNAPSHOT
    /<code>
    • 添加一个UserService类
    <code>package com.demo.starters;
    
    /**
     * @author 杨33
     * @date 2020/4/22 17:57
     */
    public class UserService {
    
        /**
         * 用户名
         */
        private String name;
    
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
    }/<code>
    • 再添加一个配置类UserServiceAutoConfiguration
    <code>package com.demo.starters;
    
    import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    /**
     * @author 杨33
     * @date 2020/4/22 18:40
     */
    @Configuration
    @ConditionalOnWebApplication
    public class UserServiceAutoConfiguration {
    
        /**
         * 实现userService对象的初始化赋值
         * @return
         */
        @Bean
        public UserService getUserName() {
            UserService userService = new UserService();
            userService.setName("张三");
            return userService;
        }
    }/<code>
    • spring.factories中给UserServiceAutoConfiguration.java设置自动配置

    spring.factories文件的存放目录必须在类路径的META-INF下。

    spring.factories的配置内容:

    <code>org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
    com.demo.starters.UserServiceAutoConfiguration/<code>

    项目的代码层级如图:

    (六)SpringBoot的启动入口main方法以及自定义starter

    自动配置项目的代码层级

    • 分别添加启动器项目和自动配置项目到maven仓库,供外部其他项目依赖
    (六)SpringBoot的启动入口main方法以及自定义starter

    install到maven仓库

    5、在外部项目,使用自定义的starter

    • pom.xml文件引入自定义的starter依赖
    <code> 
    
          com.demo.starters
          demo-spring-boot-starter
          1.0-SNAPSHOT
    /<code>
    • java代码调用自定义的依赖提供的API
    <code>package com.test.demo.springbootdemo01.controller;
    
    import com.demo.starters.UserService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    /**
     * @author yang33
     * @date 2020/4/18 15:42
     */
    @RestController
    public class HelloWordController {
    
        @Autowired
        UserService userService;
    
        /**
         * 取自定义依赖中userService对象的初始化赋值
         * @return
         */
        @GetMapping("/query")
        public String query() {
            return userService.getName();
        }
    }/<code>
    • 启动SpringBoot项目,访问http://localhost:8080/query,取到了来自自定义starter依赖包中的值。
    (六)SpringBoot的启动入口main方法以及自定义starter

    取到了自定义依赖中的值

    作者:杨33,北京互联网公司在职Java开发,专注分享写作干货。欢迎关注我,期待你的点赞评论。

    Spring Boot系列知识,下章节内容更加有料。


    分享到:


    相關文章: