The @ConditionalOnProperty is available as meta annotation (despite the #13996) but the @AliasFor does not work.
I've included a simple test showing four different bean: no condition, direct @ConditionalOnProperty, meta without alias, and meta with alias. As you can see the meta with alias does not disable the bean while the simple meta does.
My use case would be to create a @ConditionalOnModuleState meta alias with @AliasFor which could ensure that the autoconfiguration (which is loaded by spring.factories) can be turned off without removing the dependency.
package support;
import static org.assertj.core.api.Assertions.assertThatCode;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.AliasFor;
import org.springframework.test.context.TestPropertySource;
@SpringBootTest(classes = ConditionalOnPropertyTest.Config.class)
@TestPropertySource(properties = "module.enabled=false")
public class ConditionalOnPropertyTest {
@Autowired
private ApplicationContext context;
@Test
public void testReference() {
assertThatCode(() -> context.getBean("reference"))
.doesNotThrowAnyException();
}
@Test
public void testDirect() {
assertThatCode(() -> context.getBean("direct"))
.isInstanceOf(NoSuchBeanDefinitionException.class);
}
@Test
public void testModuleState() {
assertThatCode(() -> context.getBean("moduleState"))
.isInstanceOf(NoSuchBeanDefinitionException.class);
}
@Test
public void testModuleStateWithAlias() {
assertThatCode(() -> context.getBean("moduleStateWithAlias"))
.doesNotThrowAnyException();
// This should raise the exception too but the @AliasFor seems to be not working.
//.isInstanceOf(NoSuchBeanDefinitionException.class);
}
@Configuration
public static class Config {
@Bean
public Object reference() {
return new Object();
}
@Bean
@ConditionalOnProperty(prefix = "module", name = "enabled", havingValue = "true", matchIfMissing = true)
public Object direct() {
return new Object();
}
@Bean
@ConditionalOnModuleState
public Object moduleState() {
return new Object();
}
@Bean
@ConditionalOnModuleStateWithAlias("module")
public Object moduleStateWithAlias() {
return new Object();
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@ConditionalOnProperty(name = "enabled", havingValue = "true", matchIfMissing = true, prefix = "module")
public @interface ConditionalOnModuleState {
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@ConditionalOnProperty(name = "enabled", havingValue = "true", matchIfMissing = true)
public @interface ConditionalOnModuleStateWithAlias {
@AliasFor(annotation = ConditionalOnProperty.class, attribute = "prefix")
String value();
}
}
Comment From: philwebb
We had an old issue about this (#5819) but perhaps we overlooked something.
@gebezs Are you able to share the code you pasted as a complete project that we can run? It can either be a link to a GitHub project, or a zip file.
Comment From: gebezs
The difference seems to be that I use @AliasFor. I've uploaded a simple maven project with the test: conditional.zip
Comment From: wilkinsona
It's not clear to me how to fix this without breaking metaAndDirectAnnotationConditionDoesNotMatchWhenOnlyDirectPropertyIsSet. It looks like we need a variant of AnnotatedTypeMetadata.getAllAnnotationAttributes(String) that takes attribute overrides into account.
Comment From: wilkinsona
Closing in favor of #30505.