AutoConfig与Starter
大约 8 分钟
自动装配简介
SpringBoot 服务整合
- 项目的开发要求是不断进化的,而随着时间以及技术的推移,一个项目中除了基本的编程语言之外,还需要进行大量的应用服务整合,例如:在项目中会使用到 MYSQL 数据库进行持久化存储,同时会利用 Redis 实现分布式缓存,以及使用 RabbitMO 实现导松系统整合服务,这些都需要通过 Gradle 构建工具引入相关的依赖库之后才可以整合到项目之中,为项目提供应有的服务支持。

Spring 自动装配
- 在进行这些组件整合时,开发者只需要通过“xx-starter-xx”的依赖库就可以轻松实现各个服务的整合,这些程序组件在引入之后可以自动的实现装配,开发者只需要定义出核心的配置项即可使用

1、
project('microboot-web') { // 子模块
dependencies { // 配置子模块依赖
compile(project(':microboot-common')) // 引入其他子模块
compile('org.springframework.boot:spring-boot-starter-actuator')
compile(libraries.'spring-boot-starter-data-redis')
}
}
@EnableConfigurationProperties
自定义自动装配类
- 在 SpringBoot 开发框架中开发者可以直接基于“application.yml"配置文件实现某-个 Bean 对象的属性配置,注解定义配置的同时便用“@ConfigurationProperties”前缀信息,注解实现配置,而在 SpringBoot 自传统的做法是通过“@Component"动装配中,也可以通过自动配置类中的“@EnableConfigurationProperties({类.class 类.class...})”注解进行配置启用,这样就可以实现一个 Bean 对象的创建

1、
project('microboot-autoconfig-starter') { // 子模块
dependencies { // 配置子模块依赖
implementation('org.springframework.boot:spring-boot-starter-web')// 引入SpringBoot依赖
}
}
2、
package com.yootk.vo;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "muyan.yootk.dept")
public class Dept {
private Long deptno;
private String dname;
private String loc;
}
3、
package com.yootk.config;
import com.yootk.vo.Dept;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Configuration // 需要进行Bean的注册
@EnableConfigurationProperties({Dept.class}) // Bean注册
public class YootkAutoConfiguration { // 自动装配类
}
4、
package com.yootk;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class StartAutoConfigApplication {
public static void main(String[] args) {
SpringApplication.run(StartAutoConfigApplication.class, args); // 运行SpringBoot程序
}
}
5、
package com.yootk.test;
import com.yootk.StartAutoConfigApplication;
import com.yootk.vo.Dept;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.web.WebAppConfiguration;
@ExtendWith(SpringExtension.class) // 使用JUnit5测试工具
@WebAppConfiguration // 启动WEB运行环境
@SpringBootTest(classes = StartAutoConfigApplication.class) // 配置程序启动类
public class TestAutoConfig { // 编写测试类
@Autowired
private Dept dept;
@Test
public void testDept() { // 进行响应测试
System.out.println(this.dept);
}
}
6、
muyan:
yootk:
dept:
deptno: 10
dname: 沐言科技(www.yootk.com)
loc: 北京
7、
package com.yootk.test;
import com.yootk.StartAutoConfigApplication;
import com.yootk.vo.Dept;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.web.WebAppConfiguration;
@ExtendWith(SpringExtension.class) // 使用JUnit5测试工具
@WebAppConfiguration // 启动WEB运行环境
@SpringBootTest(classes = StartAutoConfigApplication.class) // 配置程序启动类
public class TestAutoConfig { // 编写测试类
@Autowired
@Qualifier("muyan.yootk.dept-com.yootk.vo.Dept") // “前缀 + 类名称”
private Dept dept;
@Test
public void testDept() { // 进行响应测试
System.out.println(this.dept);
}
}
8、
package com.yootk.test;
import com.yootk.StartAutoConfigApplication;
import com.yootk.config.YootkAutoConfiguration;
import com.yootk.vo.Dept;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.web.WebAppConfiguration;
@ExtendWith(SpringExtension.class) // 使用JUnit5测试工具
@WebAppConfiguration // 启动WEB运行环境
@SpringBootTest(classes = StartAutoConfigApplication.class) // 配置程序启动类
public class TestSpringContextBeanInfo { // 编写测试类
@Test
public void testBeanInfo() { // 进行响应测试
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(YootkAutoConfiguration.class);
String names[] = context.getBeanDefinitionNames(); // 获取Bean名称
for (String name : names) {
System.out.println("【"+name+"】" + context.getBean(name).getClass().getName());
}
}
}
@Import 注解

1、
package com.yootk.config;
import com.yootk.vo.Dept;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration // 需要进行Bean的注册
@Import({Dept.class}) // Bean注册
public class YootkAutoConfiguration { // 自动装配类
}
2、
package com.yootk.selector;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
public class DefaultImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[] {"com.yootk.vo.Dept"}; // 导入类的名称
}
}
3、
package com.yootk.config;
import com.yootk.selector.DefaultImportSelector;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration // 需要进行Bean的注册
@Import({DefaultImportSelector.class}) // Bean注册
public class YootkAutoConfiguration { // 自动装配类
}
4、
package com.yootk.regist;
import com.yootk.vo.Dept;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
public class DefaultImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
RootBeanDefinition rootBean = new RootBeanDefinition(Dept.class); // 配置Bean
registry.registerBeanDefinition("deptInstance", rootBean); // Bean注册
}
}
5、
package com.yootk.config;
import com.yootk.regist.DefaultImportBeanDefinitionRegistrar;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration // 需要进行Bean的注册
@Import({DefaultImportBeanDefinitionRegistrar.class}) // Bean注册
public class YootkAutoConfiguration { // 自动装配类
}
application.yml 配置提示
application.yml 配置提示
- 当用户在项目中引入了某些“spring-boot-starter-xx”模块后除了会引入相关的依赖库之外,实际上也会引入一些配置提示的支持,这样开发者在配置 application.yml 文件时就可以根据给出的配置项进行组件定义,而这样的配置提示,开发者也可以根据自己的需要来实现

1、
project('microboot-autoconfig-starter') { // 子模块
dependencies { // 配置子模块依赖
annotationProcessor('org.springframework.boot:spring-boot-configuration-processor')
implementation('org.springframework.boot:spring-boot-starter-web')// 引入SpringBoot依赖
}
}
2、
jar {enabled = true} // 允许当前的模块打包为“*.jar”文件
javadocTask {enabled = false} // 不启用javadoc任务
javadocJar {enabled = false} // 不生成javadoc的“*.jar”文件
bootJar {enabled = false} // 不执行SpringBoot的打包命令
3、
gradle build
自定义 Starter 组件
自动配置 Bean
- 利用自动配置类可以在容器启动时自动的进行 Bean 实例注册,由于不同的项目会存在有不同的自动配置类,所以为了便于其他模块的引用,就需要将配置类在'spring.factories”文件之中进行注册管理

1、
package com.yootk.config;
import com.yootk.regist.DefaultImportBeanDefinitionRegistrar;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import java.util.List;
@Configuration // 需要进行Bean的注册
@Import({DefaultImportBeanDefinitionRegistrar.class}) // Bean注册
public class YootkAutoConfiguration { // 自动装配类
@Bean(name = "books")
public List<String> getBookList() { // 自定义一个注册Bean对象
return List.of("Java面向对象编程", "Java就业编程实战",
"JavaWEB就业编程实战", "Spring就业编程实战",
"SpringBoot就业编程实战", "SpringCloud就业编程实战");
}
}
package com.yootk.config;
import com.yootk.vo.Dept;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.List;
@Configuration // 需要进行Bean的注册
@EnableConfigurationProperties(value={Dept.class}) // Bean注册
public class YootkAutoConfiguration { // 自动装配类
@Bean(name = "books")
public List<String> getBookList() { // 自定义一个注册Bean对象
return List.of("Java面向对象编程", "Java就业编程实战",
"JavaWEB就业编程实战", "Spring就业编程实战",
"SpringBoot就业编程实战", "SpringCloud就业编程实战");
}
}
2、
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.yootk.config.YootkAutoConfiguration
3、
project('microboot-web') { // 子模块
dependencies { // 配置子模块依赖
compile(project(':microboot-common')) // 引入其他子模块
compile(project(':microboot-autoconfig-starter')) // 引入其他子模块
compile('org.springframework.boot:spring-boot-starter-actuator')
}
}
4、
muyan:
yootk:
dept:
deptno: 10
dname: 沐言科技(www.yootk.com) —— 教学研发部
loc: 北京
5、
package com.yootk.test;
import com.yootk.StartSpringBootApplication;
import com.yootk.vo.Dept;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.web.WebAppConfiguration;
import java.util.List;
@ExtendWith(SpringExtension.class) // 使用JUnit5测试工具
@WebAppConfiguration // 启动WEB运行环境
@SpringBootTest(classes = StartSpringBootApplication.class) // 配置程序启动类
public class TestAutoConfig { // 编写测试类
@Autowired // 是由Spring容器提供的
private Dept dept;
@Autowired
private List<String> books;
@Test
public void testConfig() { // 进行响应测试
System.out.println(this.dept);
System.out.println(this.books);
}
}
SpringBoot 启动核心类
SpringBoot 基本运行结构
- 在传统的 Spring & SpringMVC 开发之中,项目的启动都极大的依赖于容器,例如:JavaSE 容器、JavaEE 容器,随后所有的组件都需要依据 XML 或 Bean 的方式进行配置然而在 SpringBoot 开发项目中,只需要引入相关的组件依赖,并编写核心的程序功能最后通过一个简单的 Java 类即可启动一个 Spring 容器,为用户提供服务
package com.yootk; // 父包,这个包中的所有子包的类会被自动扫描
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
@SpringBootApplication // 一个注解解决所有的问题
public class StartSpringBootApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(StartSpringBootApplication.class,args); // 运行SpringBoot程序
}
}
SpringApplication 构造方法
SpringBoot 应用启动
- SpringBoot 的核心应用之中需要提供有相关的应用注解之外,最为核心的就是 SpringApplication 程序类,该类实现了容器的启动、Bean 注册、WEB 容器的配置等核心功能,而在程序启动时往往会采用如下语句:
- SpringApplication.run(StartSpringBootApplication.class, args);
- 在 SpringBoot 应用程序启动时,一般会通过 SpringApplication 类中的 run()方法完成随后还需要传入程序启动类的 Class 实例,下面打开 SpringApplication.run()方法的源代码进行逐步观察。

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
this.webApplicationType = WebApplicationType.deduceFromClasspath();
this.bootstrappers = new ArrayList<>(getSpringFactoriesInstances(Bootstrapper.class));
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
SpringApplication.run()方法

public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
refreshContext(context);
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
listeners.started(context);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
return context;
}
启动内置 WEB 容器
SpringBoot 运行
- SpringBoot 的程序存在有 WEB 以及 Reactive 两种运行模式,所以在进行应用上下文创建时,就需要动态的判断当前的应用环境,而在 SpringApplication 类的构造方法中已经获取了 WebApplicationType 枚举实例,这样就可以依据此实例获取通过 createApplicationContext()方法获取 ConfiqurableApplicationContext 接囗实例 SpringApplication.createApplicationContext()方法源代码

ServletWebServerApplicationContext
AbstractApplicationContext.refresh()方法
SpringBootCLl 配置


1、
auto-configuration、starters、cli、actuator
2、
https://spring.io/projects/spring-boot#learn
https://docs.spring.io/spring-boot/docs/current/reference/html/
3、
https://repo.spring.io/release/org/springframework/boot/spring-boot-cli/2.4.3/spring-boot-cli-2.4.3-bin.zip
使用 Groovy 开发 SpringBoot 应用
1、
@RestController // Rest响应
class HelloAction {
@RequestMapping("/")
String home() {
"www.yootk.com"
}
}
2、
spring run hello.groovy -- --server.port=80
SpringBootCLl 工具管理

1、
spring init --dependencies=web,thymeleaf yootk-boot
2、
spring init --build=gradle --java-version=11 --dependencies=web,thymeleaf --packaging=war muyan-boot
3、
spring install org.springframework.boot:spring-boot-configuration-processor:2.4.5
4、
spring uninstall org.springframework.boot:spring-boot-configuration-processor:2.4.5
5、
spring uninstall --all
6、
spring shell
demo
