SpringBoot启动类大家都不陌生,只要在main方法上增加一个@SpringBootApplication注解,就可以启动了。

我们点开该注解

spring没有主启动类 springboot没有启动类_spring没有主启动类

其中关键注解为@EnableAutoConfiguration,再次跟进

spring没有主启动类 springboot没有启动类_spring没有主启动类_02


其中引入了EnableAutoConfigurationImportSelector.class,解释见下图

spring没有主启动类 springboot没有启动类_SpringBoot_03

其中关键的方法为getCondidateConfiguration(metadata attributes)

spring没有主启动类 springboot没有启动类_自动配置_04


中的SpringFactoriesLoader.loadFactoryNames(..)方法。

spring没有主启动类 springboot没有启动类_SpringBoot_05


SpringFactoriesLoader默认查找的位置就是”META-INF/spring.factories”,而在spring-boot-autoconfigure-1.4.7.jar中就有一个spring.factories。在其中配置了各种各样的AutoConfigure类。到了这一步,我们算是找到了springBoot启动时自动配置的源头。就是在spring.factories中我们通过org.springframework.boot.autoconfigure.EnableAutoConfiguration配置的启动时自动加载的自动配置类。所有的自动配置类采用了Spring4.0+的JAVA配置方法(即@Configuration+@Bean)进行配置

现在我们手写一个自动配置包
1:首先我们建立一个SpringBoot的quickstart,然后在POM文件中依赖

<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-autoconfigure</artifactId>
      <version>1.3.4.RELEASE</version>
    </dependency>

2:我们以如下图路径建立一个spring.factories的properties文件。

spring没有主启动类 springboot没有启动类_加载_06


建立好后。我们来建立一个自动配置类。为了节省空间,笔者这里就不带引入的包了。

通过引入了

@EnableConfigurationProperties(HelloServiceProperties.class)声明了配置,就可以通过@Autowired将HelloServiceProperties的实例注入进来。

//这个注解代表这个类是个配置文件
@Configuration
//这个注解代表会去自动加载HelloServiceProperties中的所有属性
@EnableConfigurationProperties(HelloServiceProperties.class)
//这个注解代表会去import com.starrk.service.HelloService;这个路径上寻找是否有类,如果有这个类,才进行加载bean
@ConditionalOnClass(HelloService.class)
//此注解会自动去application.properties中寻找prefix为hello,name/value(这两个属性是互斥的,name是value的别名)为starrk的
//当他的值为true时,加载当前类中的所有bean,当找不到时,设置为false,即不加载。
@ConditionalOnProperty(prefix = "hello",name = "starrk",havingValue = "true",matchIfMissing = false)
public class HelloServiceAutoConfigure {
    @Autowired
    private HelloServiceProperties helloServiceProperties;

    @Bean
    @ConditionalOnMissingBean(HelloService.class)//代表当没有实例时,创建一个实例。
    public HelloService helloService(){
        HelloService helloService = new HelloService();
        helloService.setMsg(helloServiceProperties.getMsg());
        return helloService;
    }

}

3:创建一个自动加载属性的类来绑定你在application.properties中配置的属性。
而HelloServiceProperties类上,如下图所示进行了配置文件绑定

@Data
@ConfigurationProperties(prefix = "hello")
public class HelloServiceProperties {
    private static final String MSG = "may the force be with you";
    private String msg =MSG;
}

这里的@Data是使用了Lombok插件,自动get/set,如果不使用可以手写,都是一样的。如果想使用可参考笔者文章


@ConfigurationProperties是将HelloServiceProperties与你在Application.properties中的属性进行了绑定,即如下图

spring没有主启动类 springboot没有启动类_spring_07

4:然后我们创建一个服务类HelloService

@Data
public class HelloService {
    private String msg;

    public String hello(){
        return "hello, "+msg;
    }

}

4:装载我们的自动配置类在spring.factories中

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.starrk.autoconfig.HelloServiceAutoConfigure

至此。自动配置包我们就建立完成。下面,我们来验证一下是否成功
创建一个SpringBoot项目,然后依赖我们刚建立的包

<dependency>
          <groupId>com.starrk</groupId>
          <artifactId>autowired</artifactId>
          <version>1.0-SNAPSHOT</version>
      </dependency>

建立启动类

@RestController
@SpringBootApplication
public class Application {
    @Autowired
    private HelloService helloService;
    @RequestMapping("/")
    public String hello(){
        return helloService.getMsg();
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class,args);
    }
}

配置application.properties/yml设置启动端口(可省略,随意)

设置端口为9000

启动当前的SpringBoot项目

得到结果

spring没有主启动类 springboot没有启动类_spring_08


我们将自动配置包中的application.properties中的文件里的hello.msg注释掉。

预期得到结果为may the force be with you

spring没有主启动类 springboot没有启动类_spring没有主启动类_09


至此,自动配置的手写及验证完成。而这就是Spring自动配置的过程。