SpringBoot自动配置的实现原理

时间:2022-09-03 21:55:48

一、运行原理

spring boot的运行是由注解@enableautoconfiguration提供的。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
@target({elementtype.type})
@retention(retentionpolicy.runtime)
@documented
@inherited
@autoconfigurationpackage
@import({enableautoconfigurationimportselector.class})
public @interface enableautoconfiguration {
  string enabled_override_property = "spring.boot.enableautoconfiguration";
 
  class<?>[] exclude() default {};
 
  string[] excludename() default {};
}

这里的关键功能是@import注解。enableautoconfigurationimportselector使用springfactoriesloader.loadfactorynames方法来扫描具有meat-inf/spring.factories文件的jar包(1.5版本以前使用enableautoconfigurationimportselector类,1.5以后这个类废弃了使用的是autoconfigurationimportselector类),下面是spring-boot-autoconfigure-1.5.4.release.jar下的meat-inf中的spring.factories文件的部分内容。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# initializers
org.springframework.context.applicationcontextinitializer=\
org.springframework.boot.autoconfigure.sharedmetadatareaderfactorycontextinitializer,\
org.springframework.boot.autoconfigure.logging.autoconfigurationreportlogginginitializer
 
# application listeners
org.springframework.context.applicationlistener=\
org.springframework.boot.autoconfigure.backgroundpreinitializer
 
# auto configuration import listeners
org.springframework.boot.autoconfigure.autoconfigurationimportlistener=\
org.springframework.boot.autoconfigure.condition.conditionevaluationreportautoconfigurationimportlistener
 
# auto configuration import filters
org.springframework.boot.autoconfigure.autoconfigurationimportfilter=\
org.springframework.boot.autoconfigure.condition.onclasscondition
 
# auto configure
org.springframework.boot.autoconfigure.enableautoconfiguration=\
org.springframework.boot.autoconfigure.admin.springapplicationadminjmxautoconfiguration,\
org.springframework.boot.autoconfigure.aop.aopautoconfiguration,\
org.springframework.boot.autoconfigure.amqp.rabbitautoconfiguration,\
org.springframework.boot.autoconfigure.batch.batchautoconfiguration,\
org.springframework.boot.autoconfigure.cache.cacheautoconfiguration,\
org.springframework.boot.autoconfigure.cassandra.cassandraautoconfiguration,\
org.springframework.boot.autoconfigure.cloud.cloudautoconfiguration,\
org.springframework.boot.autoconfigure.context.configurationpropertiesautoconfiguration,\

里面的类都是自动配置类,springboot会根据这些自动配置类去自动配置环境。

下面我们就自动动手写一个starter。

二、自定义starter

首先先介绍几个条件注解。

  • @conditionalonbean:当容器里有指定的bean为true
  • @conditionalonclass:当类路径下有指定的类为true
  • @conditionalonmissingbean:当容器里没有指定的bean为true
  • @conditionalonproperty:指定的数据是否有指定的值
  • ...

了解了条件注解后,我们开始自定义starter。

1、在自定义starter之前先要在maven中填写依赖。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?xml version="1.0" encoding="utf-8"?>
<project xmlns="http://maven.apache.org/pom/4.0.0" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance"
  xsi:schemalocation="http://maven.apache.org/pom/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelversion>4.0.0</modelversion>
 
  <groupid>cn.miaolovezhen</groupid>
  <artifactid>spring-boot-starter-test</artifactid>
  <version>0.0.1-snapshot</version>
  <packaging>jar</packaging>
 
  <name>spring-boot-starter-test</name>
  <description>demo project for spring boot</description>
 
  <parent>
   <groupid>org.springframework.boot</groupid>
   <artifactid>spring-boot-starter-parent</artifactid>
   <version>1.5.6.release</version>
   <relativepath/> <!-- lookup parent from repository -->
  </parent>
 
  <properties>
   <project.build.sourceencoding>utf-8</project.build.sourceencoding>
   <project.reporting.outputencoding>utf-8</project.reporting.outputencoding>
   <java.version>1.8</java.version>
  </properties>
 
  <dependencies>
   <dependency>
     <groupid>org.springframework.boot</groupid>
     <artifactid>spring-boot-autoconfigure</artifactid>
     <version>1.5.4.release</version>
   </dependency>
  </dependencies>
 
</project>

2、完成testproperties类,这个类定义了默认的属性值,如该类中,只有一个属性值msg,默认为world。@configurationproperties注解会定义一个匹配,如果想修改属性值,可以在application.properties中使用“匹配.属性=修改的值”进行修改。如test.msg = tan

?
1
2
3
4
5
6
7
8
9
10
11
12
13
@configurationproperties(prefix = "test")
public class testproperties {
  private static final string msg = "springboot";
  private string msg = msg;
 
  public string getmsg() {
    return msg;
  }
 
  public void setmsg(string msg) {
    this.msg = msg;
  }
}

3、完成服务类。服务类是指主要的功能类,如果没有springboot,这些服务类在spring中都是需要自己去配置生成的。如springmvc中的dispatcherservlet、mybatis的datasource等。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class testservice {
  private string msg;
 
  public string sayhello(){
    return "hello " + msg;
  }
 
  public string getmsg() {
    return msg;
  }
 
  public void setmsg(string msg) {
    this.msg = msg;
  }
}

4、完成自动配置类。自动配置类主要作用是springboot的配置核心,它会写在meat-inf/spring.factories中,告知springboot在启动时去读取该类并根据该类的规则进行配置。

  • @enableconfigurationproperties注解根据testproperties类开启属性注入,允许在application.properties修改里面的属性值。
  • @conditiononclass会检测是否存在testservice类
  • @conditiononproperty类会查看是否开启该自动配置。默认开启(true)。
  • @conditiononmissingbean会检测容器中是否有testservice类的对象,如果没有则生成一个。
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@configuration
@enableconfigurationproperties(testproperties.class)
@conditionalonclass(testservice.class)
@conditionalonproperty(prefix = "test" , value = "enabled" , matchifmissing = true)
public class testserviceautoconfiguration {
  @autowired
  testproperties testproperties;
 
  @bean
  @conditionalonmissingbean(testservice.class)
  public testservice testservice(){
    testservice testservice = new testservice();
    testservice.setmsg(testproperties.getmsg());
    return testservice;
  }
}

5、最后一步,不要忘记在在meat-inf文件夹中创建spring.factories文件。内容很简单,告诉springboot去读取testserviceautoconfiguration类。

?
1
2
org.springframework.boot.autoconfigure.enableautoconfiguration=\
cn.miaolovezhen.testserviceautoconfiguration

好啦,搞定!下面可以使用maven install命令把starter存到本地,其他springboot项目需要使用这个starter,直接导入就可以啦。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://segmentfault.com/a/1190000017780558