весенняя загрузка
Многие функции Spring Boot реализованы на основе Spring Framework, например, хорошо известные функции, которые также являются его основными функциями:Автопроводка компонентов. Он может автоматически настраивать приложения Spring Boot в соответствии с зависимыми пакетами jar, например: если класс DispatcherServlet существует в пути к классам, bean-компоненты, связанные с springMvc, будут настроены автоматически.
И все, что вам нужно, это написать класс запуска, плюс@SpringBootApplication
Аннотируйте, выполните его основной метод, а затем передайте его Sping Boot:
@SpringBootApplication
public class SpringbootApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootApplication.class, args);
}
}
Почему многие фичи Spring Boot реализованы на базе Spring framework Прежде чем входить в тему, нужно разобраться в аннотациях паттернов
аннотация схемы
Аннотации схемы Spring:
Аннотация, используемая для объявления роли «компонента» в приложении, то есть аннотированная этой аннотацией, указывающая, что класс и т. д. играет роль компонента в приложении. Например@Repository
Аннотация к классу, указывающая, что этот класс играет роль хранилища.
а также@Component
используется как общий компонент схемы, любой@Component
Все аннотированные компоненты являются кандидатами на сканирование компонентов. Точно так же любой@Component
Аннотированные аннотации, такие как@Service
, когда какой-либо компонент аннотирует его, также считается кандидатом на сканирование компонентов.
Аннотации Spring Framework | описание сцены | начальная версия |
---|---|---|
@Repository | хранилище данных | 2.0 |
@Component | Общие компоненты | 2.5 |
@Service | Служить | 2.5 |
@Controller | контроллер | 2.5 |
@Configuration | класс конфигурации | 3.0 |
Метод сборки
До весны 2.5 конфигурация xml использовалась для реализации:
<context:component-scan base-package="com.wxpay.*"/>
После весны 3.1 вы можете использовать аннотации для достижения:
@ComponentScan("com.wxpay.*")
Аннотации пользовательской схемы
Два свойства аннотаций схемы:
- Производная:
@component
,@Repository
Аннотации имеют сигнатуры значений, которые сохраняют согласованность сигнатур.Это производное от аннотаций.Другими словами, это@component
Доступны аннотированные аннотации@component
функция - Иерархический: объявление аннотаций второго уровня
SecondLevelRepository
,нашSecondLevelRepository
полученный изFirstLevelRepository
, это иерархия
Строго говоря, аннотации не являются производными и иерархическими, причина этого в том, чтобы облегчить понимание, потому что многие аннотации в Spring являются производными и иерархическими структурами.
Возможно, предыдущее утверждение недостаточно ясно, и каждый может услышать его в облаке.Далее, давайте используем пример, чтобы проиллюстрировать характеристики аннотаций режима.
Во-первых, давайте определим аннотацию, используя@Repository
Вызывать:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repository
public @interface FirstLevelRepository {
String value() default "";
}
Затем определите класс, аннотированный приведенной выше аннотацией:
@FirstLevelRepository(value = "myFirstLevelRepository")
public class MyFirstLevelRepository {
}
Наконец, определите класс начальной загрузки, который используется здесь.@ComponentScan
Отсканируйте вышеуказанный класс:
@ComponentScan("com.lingxiao.springboot.Repository")
public class RepositoryBootstrap {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext =
new SpringApplicationBuilder(RepositoryBootstrap.class).web(WebApplicationType.NONE).run(args);
MyFirstLevelRepository firstLevelRepository = applicationContext
.getBean("myFirstLevelRepository", MyFirstLevelRepository.class);
System.out.println("获取到的bean" + firstLevelRepository);
applicationContext.close();
}
}
Наконец-то получилось успешноMyFirstLevelRepository
, здесь видно, что@Repository
Аннотированные аннотации@FirstLevelRepository
, как отношения наследования, должны иметь@Repository
функция.
Затем мы определяем другую аннотацию, используя@FirstLevelRepository
обозначить это:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@FirstLevelRepository
public @interface SeondLevelRepository {
String value() default "";
}
Таким же образом используйте эту аннотацию для аннотации вышеприведенного класса.MyFirstLevelRepository
, запустите класс BootstrapRepositoryBootstrap
, также можно успешно получить боб. Это также подтверждает, что аннотация шаблонаПроизводнаяа такжеИерархический.
@SpringBootApplication также является модальной аннотацией.
Что ж, приведенный выше пример объяснил характеристики аннотации шаблона, мы можем рассмотреть его далее.@SpringBootApplication
Это аннотировано, зайдите и посмотрите исходный код:
Исходная версия — spring-boot-2.2.5.RELEASE.
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
@SpringBootConfiguration
@EnableAutoConfiguration
public @interface SpringBootApplication {
}
можно увидеть@SpringBootApplication
составная аннотация
@ComponentScan
, настроить автоматическое сканирование пакетов, нечего сказать
нажмите еще раз@SpringBootConfiguration
, мы можем видеть:
@Configuration
public @interface SpringBootConfiguration {
}
@SpringBootConfiguration
одеяло@Configuration
, проиллюстрировать@SpringBootConfiguration
и отмечено им@SpringBootApplication
является аннотацией схемы
После@EnableAutoConfiguration
, что дальше@Enable模块装配
, который также является ядром автоматической сборки
@Включить сборку модуля
Используя сборку модуля @Enable, можно настроить, какие модули будут активированы.
Реализация фреймворка | Модуль аннотаций | |
---|---|---|
Spring Framework | @EnableWebMvc | |
@EnableTransationManagement | ||
@EnableCaching | Кэширующий модуль | |
@EnableMBeanExport | JMX-модуль | |
@EnableAsync | Модуль асинхронной обработки | |
@EnableWebFlux | Модуль веб-потока | |
Spring Boot | @EnableAutoConfiguration | Модули автоматической сборки |
@EnableOAuth2Sao | Модуль единого входа OAuth2 |
Есть два способа реализовать @Enable
Реализация на основе аннотаций
Сначала определите Bean:
@Configuration
public class HelloWorldConfiguration {
@Bean
public String helloWorld() { // 方法名即 Bean 名称
return "Hello,World";
}
}
Затем определите другую аннотацию, используйте@Import
Импортируйте только что определенный компонент:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(HelloWorldConfiguration.class)
public @interface EnableHelloWorld {
}
После выполнения двух вышеуказанных шагов нам нужно только использовать@EnableHelloWorld
При аннотации класса компонент загружается в контейнер Spring.
@EnableHelloWorld
public class EnableHelloWorldBootstrap {
public static void main(String[] args) {
ConfigurableApplicationContext context = new SpringApplicationBuilder(EnableHelloWorldBootstrap.class)
.web(WebApplicationType.NONE)
.run(args);
// helloWorld Bean 是否存在
String helloWorld =
context.getBean("helloWorld", String.class);
System.out.println("获取到的bean: " + hello);
// 关闭上下文
context.close();
}
}
Запустите, чтобы увидеть эффект:
Вы можете видеть, что компонент действительно загружен в контейнер Spring.
На основе реализации, управляемой интерфейсом
выполнитьImportSelector
интерфейс, который его реализуетselectImports
метод, который возвращает массив строкового типа и имя класса, хранящееся в массиве:
public class HelloWorldImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{HelloWorldConfiguration.class.getName()};
}
}
Затем измените аннотацию, определенную выше:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
//@Import({HelloWorldConfiguration.class}) enable注解驱动的方式
@Import({HelloWorldImportSelector.class}) //接口编程的方式
public @interface EnableHelloWorld {
}
Видно, что реализация на основе интерфейса более гибкая, мы можемselectImports
Сделайте некоторые суждения, при необходимости верните разные массивы имен классов, а затем соберите их в соответствии с именами классов.
Ядро автопроводки Spring Boot
давайте оглянемся назад@EnableAutoConfiguration
Эта аннотация:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
}
нажмите еще раз@AutoConfigurationPackage
посмотри
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {
}
использовать@Import
Чтобы импортировать компонент в контейнер Spring, используйте Registrar.class.
Запустите проект springboot, отладьте, чтобы увидеть, вы можете обнаружить, что метаданные@SpringBootApplication
Аннотированный класс, посмотрите еще разnew PackageImport(metadata).getPackageName()
Значение:
Это значение представляет собой путь отсканированного пакета, то есть путь отсканированного пакета по умолчанию — это пакет и подпакет, в которых находится класс начальной загрузки.
Тогда мы увидимEnableAutoConfiguration
также используется@import
, импортированный AutoConfigurationImportSelector.class, мы можем знать из имени этого класса, что он указан для реализацииImportSelector
Интерфейс, переопределяющий метод selectImports, поэтому мы смотрим непосредственно на selectImports:
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,annotationMetadata);
return tringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
Вы можете видеть, что возвращаемый результат проходит черезautoConfigurationEntry
изgetConfigurations()
получено, поэтому мы смотрим непосредственно наgetAutoConfigurationEntry
метод:
protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
AnnotationAttributes attributes = getAttributes(annotationMetadata);
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
configurations = removeDuplicates(configurations);
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = filter(configurations, autoConfigurationMetadata);
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
Точно так же здесь мы вводимgetCandidateConfigurations
Посмотрите на метод:
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
getBeanClassLoader());
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
+ "are using a custom packaging, make sure that file is correct.");
return configurations;
}
Предположительно детская обувь, не очень хорошо владеющая английским языком, тоже может увидеть некоторые подсказки от этого, да, конечный загруженный класс конфигурации будет отMETA-INF/spring.factories
Другими словами, Spring Boot получит его из пути к классам при запуске.META-INF/spring.factories
Указанное значение импортируется в контейнер как класс конфигурации в файле, реализующем автоматическую настройку.
Условная сборка
Существует два типа аннотаций условной сборки:
Весенние аннотации | описание сцены | начальная версия |
---|---|---|
@Profile | Настраиваемая условная сборка | 3.1 |
@Conditional | Программирование условной сборки | 4.0 |
После 4.0 @profile также стал @Conditional для достижения
Сценарий приложения: обычно используется для переключения между производственной средой и средой разработки, то есть для добавления аннотаций к классам или методам и установки идентификаторов среды, таких какjava7
,java8
, мы покажем, как использовать простое многоцелое суммирование
@Profile реализует условную сборку
Сначала определите интерфейс:
public interface CalCulateService {
/**
* 整数求和
* @param args
* @return
*/
Integer sum(Integer... args);
}
Затем реализуйте метод суммирования для JDK7 и JDK8 соответственно.
Первый — это реализация JDK7:
/**
* java7的方式实现求和
*/
@Profile("Java7")
@Service
public class Java7CalCulateServiceImpl implements CalCulateService {
@Override
public Integer sum(Integer... args) {
System.out.println("java7的方式求和");
int sum = 0;
for (int i = 0; i < args.length; i++) {
sum+=args[i];
}
return sum;
}
}
Затем идет реализация JDK8:
@Profile("Java8")
@Service
public class Java8CalCulateServiceImpl implements CalCulateService {
@Override
public Integer sum(Integer... args) {
System.out.println("java8的方式求和");
int sum = Stream.of(args).reduce(0,Integer::sum);
return sum;
}
}
Затем создайте класс запуска, при запуске контейнера используйте.profiles("Java8")
чтобы указать, какую версию использовать для расчета:
@SpringBootApplication(scanBasePackages = "com.lingxiao.springboot.service")
public class CalCulateServiceBootstrap {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext =
new SpringApplicationBuilder(CalCulateServiceBootstrap.class)
.web(WebApplicationType.NONE)
.profiles("Java8")
.run(args);
CalCulateService calCulateService = applicationContext
.getBean(CalCulateService.class);
System.out.println("求和: " + calCulateService.sum(1,2,3,4,5));
applicationContext.close();
}
}
результат операции:
Вы можете видеть, что это действительно суммирование, реализованное способом java8.
@Conditional реализует условную сборку
При создании бина добавляется ряд условий, только при выполнении всех указанных условий компонент может быть зарегистрирован. В использовании@Conditional
Когда класс условного суждения должен реализоватьCondition
интерфейс
Теперь настраиваем условную сборку и создаем аннотацию:
/**
* 编程方式实现条件装配
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD})
@Documented
@Conditional(OnSystemPropertyCondition.class)
public @interface ConditionalOnSystemProperty {
/**
* java系统属性名称
* @return
*/
String name();
/**
* java系统属性值
*/
String value();
}
В этой аннотации определены два свойстваname
а такжеvalue
, эти два свойства используются при реализации условного сужденияOnSystemPropertyCondition
будет использоваться в.
Создайте класс условного суждения:
/**
* 编程方式实现条件装配
*/
public class OnSystemPropertyCondition implements Condition {
/**
*
* @param context
* @param metadata 源信息
* @return
*/
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
MultiValueMap<String, Object> attributes = metadata.getAllAnnotationAttributes(ConditionalOnSystemProperty.class.getName());
List<Object> nameObj = attributes.get("name");
String name = "";
if (!CollectionUtils.isEmpty(nameObj)) {
name = String.valueOf(attributes.get("name").get(0));
}
String value = "";
if (!CollectionUtils.isEmpty(nameObj)) {
value = String.valueOf(attributes.get("value").get(0));
}
String property = System.getProperty(name);
return value.equals(property); //条件满足才会返回装配
}
}
использоватьmetadata.getAllAnnotationAttributes
Получите значение атрибута в аннотации, а затем оцените, выполняется ли условие, и сборка не будет выполняться, пока условие не будет выполнено.
Создайте класс начальной загрузки:
public class ConditionalOnSystemPropertyBootstrap {
@Bean
@ConditionalOnSystemProperty(name = "java.vm.specification.version",value = "1.8")
public String helloWorld(){
return "hello world";
}
public static void main(String[] args) {
ConfigurableApplicationContext context = new SpringApplicationBuilder(ConditionalOnSystemPropertyBootstrap.class)
.web(WebApplicationType.NONE)
.run(args);
String helloWorld = context.getBean("helloWorld", String.class);
System.out.println("bean name: "+helloWorld);
context.close();
}
}
В этом классе начальной загрузки мы объявляем bean-компонент helloWorld и добавляем к этому методу аннотацию условной сборки, гдеjava.vm.specification.version
Является ли полученная версия виртуальной машины Java, если виртуальная машина 1.8, bean-компонент будет загружен в контейнер Spring
Когда текущая версия 1.8, запустите код:
С нормальной загрузкой проблем нет, когда переключаем версии, снова запускаем:
Было обнаружено, что было сообщено об ошибке, и Spring не смог найти бин, что означает, что бин не соответствует условиям для загрузки.
Реализовать автоматическую сборку
Рори так много сказал, давайте посмотрим, как реализовать автопроводку Spring Boot.
Автоматическая сборка Spring Boot сочетает в себе вышеупомянутые технологии, поэтому мы можем реализовать автоматическую сборку на основе знаний Spring Framework.Этапы следующие:
- Реализовать класс, который необходимо собрать
- Весенняя загрузка фабрики, настройте классы, которые необходимо собрать
- Класс реализации: SpringFactoryLoader
- Ресурсы конфигурации: META-INF/spring.factories
- Активировать автопроводку — @EnableAutoConfiguration
Сначала создайте класс:
/**
* 自动装配
*/
@Configuration //模式注解
@EnableHelloWorld //Enable模块装配
@ConditionalOnSystemProperty(name = "java.vm.specification.version",value = "1.8") //条件装配
public class HelloWorldAutoConfiguration {
}
Как видите, все три модифицированные аннотации основаны на Spring Framework.Теперь нам нужно только настроить файл spring.factories.Мы создаем новый файл в каталоге ресурсов:
Содержимое находится в формате ключ-значение, а ключ@EnableAutoConfiguration
, value — это путь к пакету класса autowired:
# 自动装配
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.lingxiao.springboot.configuration.HelloWorldAutoConfiguration
Затем создайте еще один класс запуска:
@EnableAutoConfiguration
public class EnableAutoConfigurationBootstrap {
public static void main(String[] args) {
ConfigurableApplicationContext context = new SpringApplicationBuilder(EnableAutoConfigurationBootstrap.class)
.web(WebApplicationType.NONE)
.run(args);
String hello = context
.getBean("helloWorld", String.class);
System.out.println("获取到的bean: " + hello);
context.close();
}
}
Результатом операции является правильное получение боба. Вот краткое изложение всего процесса:
- использовать
@EnableAutoConfiguration
Активируйте автопроводку, и Spring Boot пойдетspring.factories
Разберите классы, которые должны быть автоматически подключены в файлеHelloWorldAutoConfiguration
- сборка
HelloWorldAutoConfiguration
Когда пришло время судить, соответствует ли она требованиям сборки, вот среда jdk1.8, значит, она соответствует требованиям. -
HelloWorldAutoConfiguration
находится@EnableHelloWorld
отмеченный,@EnableHelloWorld
пройти через@Import({HelloWorldImportSelector.class})
способ введенияHelloWorldImportSelector
- существует
HelloWorldImportSelector
изselectImports
метод возвращенHelloWorldConfiguration
имя класса - существует
HelloWorldConfiguration
загрузкаhelloWorld
Исходный код загружен на gitee:Нажмите, чтобы посетить
Ссылаться на: