Spring может анализировать классы @Configuration, используя ClassReader.
Предположим, что у нас есть следующий сценарий
У нас есть класс автоконфигурации с несколькими определениями @Bean.
У одного из @Bean все условия выполнены, а у второго @Bean есть @ConditionalOnClass, и класс отсутствует в пути к классу.
@Configuration
class CustomConfiguration {
@Bean
@ConditionalOnClass(String.class)
String knownClass() {
return "Hello";
}
@Bean
@ConditionalOnClass(MissingClass.class)
MissingClass secondBean() {
return new MissingClass();
}
}
В этом сценарии у меня есть пара вопросов
ApplicationContext?@Bean срабатывать во время отладки?*AutoConfiguration загружается в JVM, поскольку этот класс будет ссылаться на другие классы (из второго @Bean), которые не могут быть разрешены во время загрузки класса.@Bean и вызывает ли этот метод?Спасибо




Вообще говоря, вам следует избегать использования @ConditionalOnClass в методе @Bean именно по этой причине. Эта ситуация описана в справочная документация, где рекомендуется использовать отдельный класс @Configuration для изоляции состояния @ConditionalOnClass.
Чтобы ответить на ваши конкретные вопросы:
@Bean.@Bean, класс должен успешно загрузиться. Если неразрешимый класс используется в сигнатуре метода @Bean (обычно тип возвращаемого значения), класс не загрузится.Как отмечено в документации, указанной выше, вместо того, чтобы беспокоиться о сценариях, описанных в 3, и о том, что будет работать, а что нет, рекомендуется использовать отдельный, возможно, вложенный класс @Configuration с условием на уровне класса. Для вашего конкретного примера это будет выглядеть так:
@Configuration
class CustomConfiguration {
@Bean
@ConditionalOnClass(String.class)
String knownClass() {
return "Hello";
}
@Configuration
@ConditionalOnClass(MissingClass.class)
static class DoubtfulBeanConfiguration {
@Bean
MissingClass missingClass() {
return new MissingClass();
}
}
}
Я считаю, что образец в моем примере выдаст ошибку NoClassDefFound.
Да, это будет. Отсюда рекомендация не делать то, что делает ваш пример.
Я добавил пример с предложенным вами решением самого вопроса. Если это правильно, можете ли вы добавить это к своему ответу, чтобы я мог удалить его из вопроса. Спасибо за вашу помощь!!
Я добавил конкретный пример того, как все должно быть структурировано.
Энди выше ответил на вопрос "как", т.е. как пользоваться библиотекой. Но в этом ответе я попытался ответить на вопрос, почему
вот мое понимание
Spring читает метаданные файла автоконфигурации из /META-INF/spring-autoconfigure-metadata.properties из пути к классам (один такой файл присутствует в spring-boot-autoconfigure).
@Configuration.
классы, перечисленные в
ключ org.springframework.boot.autoconfigure.EnableAutoConfiguration
в файле /META-INF/spring.factories плагином spring-boot-autoconfigure-processor@Configuration, такие как @ConditionalOnClass, @AutoConfigureBefore,
и т.д]@Configuration, полученных из указанного выше файла свойств.@Configuration, включая @ConditionalOnClass, в сравнении с текущим путем к классам и фабрикой компонентов. Если условия выполняются, он загружает класс @Configuration, используя стандартную загрузку классов Java.@ConditionalOnClass(MissingClass.class) на уровне @Configuration, spring просто не загрузит класс, загрузит класс конфигурации, если условия уровня класса не оцениваются как истинные, скажем, если класс отсутствует в пути к классам@ConditionalOnClass(MissingClass.class) на уровне @Bean, spring попытается загрузить наш класс @Configuration (при условии, что все условия на уровне класса @Configuration выполнены), и мы получим NoClassDefFoundError во время загрузки класса.В целом, по этой причине нам нужно следовать решению @Andy.
@Энди
Спасибо, если вы можете высказать свое мнение о том, как Spring реализовал внутри себя функцию @ConditionalOnClass.
Спасибо
Обновил вопрос с примером