Beans added dynamically are not considered by ConditionalOnBean

Viewed 66

I am registering beans dynamically at startup with BeanDefinitionRegistryPostProcessor:

Bean class:

@RequiredArgsConstructor
public class DynamicBean {

    private final String name;
    private final Object value;

}

Properties class:

@Data
public class DynamicProperties {
    private List<Bean> beans;

    @Data
    public static class Bean {
        private String name;
        private Object value;
    }
}

BeanDefinitionRegistryPostProcessor:

@Configuration
public class DynamicBeanRegistrar implements BeanDefinitionRegistryPostProcessor {

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        DynamicProperties dynamicProperties = Binder.get(environment)
                .bind("dynamic", Bindable.of(DynamicProperties.class))
                .orElseThrow(IllegalStateException::new);

        dynamicProperties.getBeans().forEach(bean -> {
            GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
            beanDefinition.setBeanClass(DynamicBean.class);

            String beanName = bean.getName();

            ConstructorArgumentValues cav = new ConstructorArgumentValues();
            cav.addGenericArgumentValue(bean.getName());
            cav.addGenericArgumentValue(bean.getValue());
            beanDefinition.setConstructorArgumentValues(cav);

            beanDefinitionRegistry.registerBeanDefinition(beanName, beanDefinition);
            log.info("Registered dynamic bean")
        });
    }


    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        // noop
    }
}

I also have another configuration class using @ConditionalOnBean annotation for some beans:

@Configuration(proxyBeanMethods = false)
public class AnotherConfiguration {

    @Bean
    public Object a() {
        return new Object ();
    }

    @Bean
    public Object b() {
        return new Object ();
    }

    @Bean
    @ConditionalOnBean(DynamicBean.class)
    public Object x() {
        return new Object();
    }

    @Bean
    @ConditionalOnBean(DynamicBean.class)
    public Object y() {
        return new Object();
    }
}

The problem is that the @ConditionalOnBean annotation doesn't seem to know about the dynamically registered beans and is therefore evaluating as false, causing beans x and y not to be created. I have tried using @AutoConfigureBefore(AnotherConfiguration.class) on my DynamicBeanRegistrar as well as implementing PriorityOrdered, but that didn't seem to have any effect.

Is there any way to achieve the expected behaviour?

0 Answers
Related