чтение урожая
- 👍🏻Научитесь настраивать Spring-Boot-Starter
- 👍🏻Понять принцип автоматической настройки SpringBoot
Загрузка исходного кода этой главы
Что такое стартер
Стартер — очень важная концепция в Spring Boot, Стартер эквивалентен модулю, который может интегрировать зависимости, необходимые модулю, и автоматически настраивать bean-компоненты в модуле в соответствии со средой (условиями).
Пользователям нужно только полагаться на Starter соответствующей функции, без особой настройки и зависимостей, Spring Boot может автоматически сканировать и загружать соответствующий модуль и устанавливать значение по умолчанию, чтобы его можно было использовать из коробки.
Зачем использовать Стартер
В нашей повседневной работе по разработке часто есть какие-то модули конфигурации, которые не зависят от бизнеса, мы часто помещаем их в определенный пакет, а затем, если в другом проекте нужно повторно использовать эту функцию, код должен быть жестко скопирован в другой проект и реинтегрировать его крайне проблематично.
Если мы инкапсулируем эти функциональные модули конфигурации, которые могут быть независимыми от бизнес-кода, в стартер, и установим значение по умолчанию в стартере, нам нужно будет только ссылаться на зависимость в pom при повторном использовании, и Spring Boot сделает это за нас. Полная автоматическая сборка, сделать开箱即用
.
Автоматическая настройка Springboot
Стартер в SpringBoot — это очень важный механизм, который позволяет отказаться от предыдущей сложной конфигурации и интегрировать ее в стартер.Пользователю нужно только ввести зависимость стартера в maven, и Spring Boot может автоматически сканировать путь к классам под каждым jar-пакетом. Файл spring.factories загружает информацию о классе автоконфигурации, загружает соответствующую информацию о компонентах и запускает соответствующий默认配置
.
Spring Boot предоставляет модули зависимостей spring-boot-starter для разработки различных сценариев для ежедневных корпоративных приложений. Все эти зависимые модули следуют обычной конфигурации по умолчанию и позволяют нам настраивать эти конфигурации, т.е. следовать "约定大于配置
" концепция.
Вы можете взглянуть на статью, которую я написал ранее, в которой подробно описан процесс автоматической настройки Springboot:Разберитесь с принципом автоматической настройки SpringBoot в одной статье — Nuggets (juejin.cn)
spring.factories
Spring Boot по умолчанию сканирует тот же пакет, что и класс запуска. Если наш Starter и класс запуска не находятся в одном и том же основном пакете, нам нужно настроить файл spring.factories, чтобы конфигурация вступила в силу. Spring Boot загружает spring пути к классам в каждом пакете jar по умолчанию.factory файл, сконфигурированный ключorg.springframework.boot.autoconfigure.EnableAutoConfiguration
Общие аннотации для разработки Starter
Использование аннотаций значительно облегчило нашу разработку, и нам больше не нужно писать файлы конфигурации XML.SpringBoot загружает класс автоматической конфигурации, просматривая файл spring.factories, а класс автоматической конфигурации определяет различные условия оценки во время выполнения, такие как @ ConditionalOnMissingBean(A .class) и т. д., пока в контейнере ioc не указана информация о bean-компоненте типа A, файл конфигурации вступит в силу.
@Conditional — это новая аннотация, предоставленная Spring 4. Ее функция — оценивать в соответствии с определенными условиями и регистрировать bean-компоненты для контейнера, если условия выполняются.
- аннотация сопоставления свойств
- @ConfigurationProperties: сопоставление значений свойств файла конфигурации и классов сущностей.
- @EnableConfigurationProperties: используется вместе с @ConfigurationProperties, добавляет класс, измененный @ConfigurationProperties, в контейнер ioc.
- Настройка аннотаций компонентов
- @Configuration: идентифицирует класс как класс конфигурации и внедряет класс в контейнер ioc.
- @Bean: обычно используется в методах, объявляет bean-компонент, имя bean-компонента — это имя метода по умолчанию, а тип — возвращаемое значение.
- Условная аннотация
- @Conditional: он создает определенный bean-компонент на основе класса условия.Класс условия должен реализовать интерфейс условия и переписать интерфейс совпадений, чтобы построить условие оценки.
- @ConditionalOnBean: экземпляр bean-компонента будет создан только в том случае, если указанный bean-компонент существует в контейнере.
- @ConditionalOnMissingBean: если указанный bean-компонент не существует в контейнере, будет создан экземпляр bean-компонента.
- @ConditionalOnClass: экземпляр Bean будет создан только в том случае, если в системе есть указанный класс.
- @ConditionalOnMissingClass: экземпляр Bean будет создан только в том случае, если в системе не указан класс.
- @ConditionalOnExpression: экземпляр Bean будет создан только тогда, когда выражение SpEl истинно
- @AutoConfigureAfter : создать экземпляр компонента после его автоматической настройки.
- @AutoConfigureBefore : создать экземпляр компонента до его автоматической настройки.
- @ConditionalOnJava: соответствует ли версия в системе требованиям.
- @ConditionalOnSingleCandidate: создание экземпляра триггера, когда указанный bean-компонент имеет только один в контейнере или их несколько, но указан предпочтительный bean-компонент
- @ConditionalOnResource: существует ли указанный файл ресурсов в пути к классам.
- @ConditionalOnWebApplication: веб-приложение
- @ConditionalOnNotWebApplication: не веб-приложение
- @ConditionalOnJndi: JNDI указывает, что элемент существует
- @ConditionalOnProperty: настроить правила загрузки конфигурации.
- prefix : префикс имени свойства конфигурации.
- value : Массив, получить значение соответствующего имени свойства, нельзя использовать одновременно с именем
- name : массив, который можно использовать в сочетании с префиксом для формирования полного имени свойства конфигурации, нельзя использовать одновременно со значением
- haveValue : Сравните, совпадает ли полученное значение атрибута со значением, заданным с помощью haveValue, и загрузите конфигурацию только в том случае, если они совпадают.
- matchIfMissing : следует ли загружать, если это свойство конфигурации отсутствует. Если true, он будет нормально загружаться без этого свойства конфигурации; в противном случае он не вступит в силу.
Полный режим и легкий облегченный режим
- Параметр @Configuration proxyBeanMethods:
- Полный режим (по умолчанию):
@Configuration(proxyBeanMethods = true)
- В том же классе конфигурации при прямом вызове @Bean изменен
方法
введенный объект, затем вызовите该方法会被代理
, возьмите столбец экземпляра компонента из контейнера ioc, чтобы столбец экземпляра был таким же. То есть один экземпляр объекта, в этом режиме SpringBoot будет проверять наличие компонента в контейнере при каждом запуске.
- В том же классе конфигурации при прямом вызове @Bean изменен
- Облегченный облегченный режим:
@Configuration(proxyBeanMethods = false)
- В том же классе конфигурации при прямом вызове @Bean изменен
方法
введенный объект, затем вызовите该方法不会被代理
, что эквивалентно вызову общего метода напрямую, конструктор будет, но жизненного цикла бина нет, и будут возвращаться разные экземпляры.
- В том же классе конфигурации при прямом вызове @Bean изменен
- Полный режим (по умолчанию):
- Примечание. proxyBeanMethods предназначен для использования аннотации @Bean.
方法
быть проксированным. Вместо установки параметров singleton и нескольких экземпляров @Bean. - Пример теста здесь не показан, вы можете скачать мой код для просмотра
@Configuration(proxyBeanMethods = false)
public class AppConfig {
//放一份myBean到ioc容器
@Bean
public Mybean myBean() {
return new Mybean();
}
//放一份yourBean到ioc容器
@Bean
public YourBean yourBean() {
System.out.println("==========");
//注意:@Configuration(proxyBeanMethods = false):myBean()方法不代理,直接调用
//注意:@Configuration(proxyBeanMethods = true):myBean()方法代理,从ioc容器拿
return new YourBean(myBean());
}
}
Когда использовать полный режим, а когда облегченный облегченный режим?
- Когда есть зависимости между экземплярами bean-компонентов, внедренными в контейнер в одном и том же классе конфигурации, рекомендуется использовать полный режим.
- Когда нет зависимости между экземплярами bean-компонентов, внедренными в контейнер в одном и том же классе конфигурации, рекомендуется использовать облегченный режим Lite для повышения скорости запуска и производительности springboot.
Соглашение об именах для начинающих
- Официальный Spring Starter обычно называется spring-boot-starter-{name}, например: spring-boot-starter-web
- Spring официально рекомендует, чтобы имена неофициальных Starters соответствовали формату {name}-spring-boot-starter: например, mybatis-spring-boot-starter.
Стартер разработки
1. Создайте стартовый проект
新建项目后,要删除main启动类
2. Добавьте зависимости
<?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">
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.ljw</groupId>
<artifactId>ljw-spring-boot-starter</artifactId>
<version>1.0</version>
<properties>
<java.version>1.8</java.version>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- 包含自动配置的代码-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- 配置文件点击可以跳转实体-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>
我们没有main入口,需要去除pom文件中maven打包插件spring-boot-maven-plugin
- Роль spring-boot-configuration-processor:
- spring-boot-configuration-processor на самом деле является обработчиком аннотаций, который работает на этапе компиляции.Как правило, объявления в maven являются необязательными как истинные
- Вы можете щелкнуть порт в идее, ввести это поле, и вы также можете увидеть информацию о подсказке конфигурации.
- Это связано с тем, что в вашем файле ресурсов есть файл spring-configuration-metadata.json, который является метаданными конфигурации spring в форме json.
3. Напишите класс атрибута
@ConfigurationProperties может определить класс информации о конфигурации и сопоставить его с файлом конфигурации.
@ConfigurationProperties(prefix = "ljw.config")
public class HelloProperties {
private String name = "hello 默认值!";
private int age = 8;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
4. Пользовательский бизнес-класс
Здесь вы можете имитировать некоторые бизнес-классы, которые получили информацию о файле конфигурации для бизнес-операций.
public class HelloService {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String hello() {
return "HelloService{" +
"name='" + name + ''' +
", age=" + age +
'}';
}
}
5. Напишите класс автоконфигурации
Соглашение об именах: XxxAutoConfiguration
@Configuration(proxyBeanMethods = false)
// 当存在某个类时,此自动配置类才会生效
@ConditionalOnClass(value = {HelloService.class})
// 导入我们自定义的配置类,供当前类使用
@EnableConfigurationProperties(value = HelloProperties.class)
// 只有非web应用程序时此自动配置类才会生效
@ConditionalOnWebApplication
//判断ljw.config.flag的值是否为“true”, matchIfMissing = true:没有该配置属性时也会正常加载
@ConditionalOnProperty(prefix = "ljw.config", name = "flag", havingValue = "true", matchIfMissing = true)
public class HelloAutoConfiguration {
/**
* @param helloProperties 直接方法签名入参注入HelloProperties,也可以使用属性注入
* @return
*/
@Bean
@ConditionalOnMissingBean(HelloService.class)
//@ConditionalOnProperty(prefix = "ljw.config", name = "flag", havingValue = "true", matchIfMissing = true)
public HelloService helloService(HelloProperties helloProperties) {
HelloService helloService = new HelloService();
//把获取的信息注入
helloService.setName(helloProperties.getName());
helloService.setAge(helloProperties.getAge());
return helloService;
}
}
Примечание. Здесь можно внедрить только веб-приложение, и независимо от того, является ли значение ljw.config.flag «истинным» или ключ не может быть настроен для внедрения службы HelloService.
6. Напишите spring.factories
Настройте класс автоматической конфигурации HelloAutoConfiguration на ключ org.springframework.boot.autoconfigure.EnableAutoConfiguration, springboot автоматически загрузит файл и соберет его в соответствии с условиями
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.ljw.starter.config.HelloAutoConfiguration
7. Напишите файл запроса конфигурации (необязательно)
additional-spring-configuration-metadata.json
После настройки файла Additional-spring-configuration-metadata.json очень эффективно использовать лично написанную конфигурацию для чтения в инструменте IDE разработчика.application.properties
илиapplication.yml
Подсказка о завершении файла.
Настройте подробные параметры формата для просмотра документации
моя конфигурация:
{"properties": [
{
"name": "ljw.config.name",
"type": "java.lang.String",
"defaultValue": "hello 默认值!这里配置的是提示,真正默认值在Properties里面",
"description": "这是字符串名称啊."
},
{
"name": "ljw.config.age",
"defaultValue": 8,
"description": "这是int类型的年龄啊.",
"deprecation": {
"reason": "过时原因.",
"replacement": "替代key是:ljw.config.age22",
"level": "warning"
}
}
]}
Пожалуйста, обратитесь к следующемуproperties
Таблица для понимания конфигурации.
название | тип | Цель |
---|---|---|
name | String | Полное название объекта. Имена пишутся строчными буквами, разделенными циклами (например, server.address). Это свойство является обязательным. |
type | String | Полная подпись типа данных свойства (например, java.lang.String ), а также полный универсальный тип (например, java.util.Map如果类型未知或基本类型,则可以省略。 |
description | String | Краткое описание группы, которое может отображаться пользователю. Может быть опущен, если описание отсутствует. Предлагаемые описания представляют собой короткие абзацы с кратким изложением в первой строке. Последняя строка описания должна заканчиваться точкой (.). |
sourceType | String | Имя класса источника, предоставившего это свойство. Например, если свойство относится к классу с аннотацией @ConfigurationProperties, это свойство будет содержать полное имя этого класса. Может быть опущен, если тип источника неизвестен. |
defaultValue | Object | Значение по умолчанию, которое используется, если атрибут не указан. Если типом свойства является массив, это может быть массив значений. Может быть опущен, если значение по умолчанию неизвестно. |
deprecation | множество | Устаревшее описание. |
deprecation
каждыйproperties
Объект JSON, содержащийся в свойствах элемента, может содержать следующие свойства:
название | тип | Цель |
---|---|---|
level | String | Уровень устаревания: предупреждение (по умолчанию) или ошибка. Когда свойство имеет уровень предупреждения об устаревании, оно все равно должно быть привязано к среде. Однако, когда оно имеет уровень устаревания ошибки, свойство больше не управляется и не ограничивается. |
reason | String | Краткое описание того, почему это свойство устарело. Может быть опущен, если нет причин. Предлагаемые описания представляют собой короткие абзацы с кратким изложением в первой строке. Последняя строка описания должна заканчиваться точкой (.). |
replacement | String | Полное имя свойства, которое заменяет это устаревшее свойство. Если этот атрибут не заменяется, его можно опустить. |
spring-configuration-metadata.json
Объем кода в spring-configuration-metadata.json довольно большой, для удобства можно сгенерировать его через IDE, здесь мы используем идею.
Найдите Обработчики аннотаций в настройках идеи, затем установите флажок Включить обработку аннотаций для завершения. См. автоматически сгенерированный файл spring-configuration-metadata.json в скомпилированном и упакованном файле. Этот файл не требует от нас записи
Автоматически генерируется следующее:
{
"groups": [
{
"name": "ljw.config",
"type": "com.ljw.starter.properties.HelloProperties",
"sourceType": "com.ljw.starter.properties.HelloProperties"
}
],
"properties": [
{
"name": "ljw.config.name",
"type": "java.lang.String",
"description": "这是字符串名称啊.",
"sourceType": "com.ljw.starter.properties.HelloProperties",
"defaultValue": "hello 默认值!这里配置的是提示,真正默认值在Properties里面"
},
{
"name": "ljw.config.age",
"type": "java.lang.Integer",
"description": "这是int类型的年龄啊.",
"sourceType": "com.ljw.starter.properties.HelloProperties",
"defaultValue": 8,
"deprecated": true,
"deprecation": {
"level": "warning",
"reason": "过时原因.",
"replacement": "替代key是:ljw.config.age22"
}
}
],
"hints": []
}
Протестируйте стартер
1. Предокружение
install для упаковки пользовательского начального проекта:ljw-spring-boot-starter
Новый проект:ljw-test-spring-boot-starter
2. Добавьте зависимости
Представить упакованный пользовательский стартер
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- 测试web应用-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--自定义satrter-->
<dependency>
<groupId>com.ljw</groupId>
<artifactId>ljw-spring-boot-starter</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
3. Тестовый класс
@Service
public class TestController implements CommandLineRunner {
/**
* 注入自定义starter服务
*/
@Resource
private HelloService helloService;
@Override
public void run(String... args) throws Exception {
System.out.println(helloService.hello());
}
}
4. Измените файл конфигурации
Введите префикс, чтобы увидеть, что подсказка уже есть
ljw.config.name=ljw hello!
ljw.config.age=99
ljw.config.flag=true
#不会注入
#ljw.config.flag=true1
# 可以看到哪些自动配置了
debug=true
5. Запустите программу для печати
HelloService{name='ljw hello!', age=99}
- Условный впрыск
- Невозможно внедрить службу HelloService без зависимости от spring-boot-starter-web
- Если параметр ljw.config.flag настроен и значение не равно true, служба HelloService не может быть внедрена, если ljw.config.flag не настроена, ее можно внедрить.
6. Просмотрите способ применения класса автоматической настройки.
Когда консоль печатает отчет об автоконфигурации, включив свойство debug=true, можно легко узнать, какие классы автоконфигурации действуют.
HelloAutoConfiguration matched:
- @ConditionalOnClass found required class 'com.ljw.starter.service.HelloService' (OnClassCondition)
- @ConditionalOnWebApplication (required) found 'session' scope (OnWebApplicationCondition)
- @ConditionalOnProperty (ljw.config.flag=true) matched (OnPropertyCondition)
HelloAutoConfiguration#helloService matched:
- @ConditionalOnMissingBean (types: com.ljw.starter.service.HelloService; SearchStrategy: all) did not find any beans (OnBeanCondition)
- 👍🏻: Если у вас есть прибыль, пожалуйста, поставьте лайк и поддержите!
- ❤️: Любимые статьи для удобного просмотра!
- 💬: Обменивайтесь комментариями и развивайтесь друг с другом!