Учитывая интерфейс и класс реализации, подобный этому.
interface MyBean{
suspend fun suspend isEnabled(name:String): Boolean
}
@Service("myBean")
@NoArg // I created an annotation and configured the noarg plugin
//to satisfy Spring EL's `noarg default constructor` requirements.
class MyMbean(val antoherBean: AnotherBean): MyBean{
override suspend fun isEnabled(name:String): Boolean{
}
}
При нанесении на @ConditonalOnExpression
вот так.
@Configuration
@ConditionalOnExpression("#myBean.isEnabled('test')")
class MyConfig{}
Что касается строки EL, я пробовал #{myBean.isEnabled('test')}
и т. д. Ничего не помогло.
EL1008E: Property or field 'myBean' cannot be found on object of type
'org.springframework.beans.factory.config.BeanExpressionContext'
- maybe not public or not valid?
Я использовал последнюю версию Spring Boot 3.3.1 и Kotlin 2.0.0/Kotlin Coroutines 1.8.x.
Обновление: я пытался удалить модификатор suspend
, но все равно столкнулся с ошибкой.
Я попробовал удалить suspend
на простом примере, получил тот же результат.
Обычно мы используем аннотацию @Configuration
как место, где определяются «основные» компоненты.
А затем используйте аннотацию @Component
(или @Service
, @Repository
), чтобы определить «конкретные» компоненты, которые используют «основные» компоненты.
Вот почему класс MyConfig
будет инициализирован раньше MyMbean
класса.
Если хочешь, попробуй, сделай это. Предлагаю 2 решения:
Решение 1
Сделайте MyConfig
зависимым от myBean
и переместите @ConditionalOnExpression
при создании метода компонента:
@Configuration
@ConditionalOnBean(name = "myBean")
public class MyConfig {
@Bean
@ConditionalOnExpression("@myBean.isEnabled('test')")
public String simpleBean() {
return "simpleBean";
}
}
Примечание: используйте @
, чтобы получить ссылки на компоненты.
Решение 2
Вам необходимо настроить собственное условие и создать компонент вручную:
@Configuration
@Conditional(MyBeanCondition.class)
public class MyConfig {}
public class MyBeanCondition implements ConfigurationCondition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
MyMbean mybean = context.getBeanFactory().createBean(MyMbean.class);
return mybean.isEnabled("test");
}
@Override
public ConfigurationPhase getConfigurationPhase() {
return ConfigurationPhase.REGISTER_BEAN;
}
}
Для выполнения функции приостановки необходимо находиться в контексте сопрограммы и, как правило, иметь ее поддержку. Я сомневаюсь, что Spring делает это для
@ConditionalOnExpression
. Если это что-то простое, например чтение из файла и т. д., я предлагаю создать еще одну функцию, которая обертывает первую вrunBlocking
. Это проще всего сделать и не должно вызвать проблем.