简体   繁体   中英

How to tell Spring to check again the ConditionalOnBean during the app runtime?

On some beans, I'm using ConditionalOnBean ( a and b in the example). At the time the app starts, the bean that is conditional on it does not exist. Therefore, the bean ( yoni in the example) under the annotation ( ConditionalOnBean ) are not initialized and are not processed by Spring. During the course of running the app, the bean is dynamically added to the context (see addYoni in the example). In order to initialize the beans that now pass the conditions ( a and b in the example), I need to tell Spring to check all the conditionals again. It should be noted that in the real world I do not know which classes are under the relevant condition (in fact, some of them have not yet been written).

If it is possible, how can it be done?

@ConditionalOnBean(name = "yoni")
@Service
public class a {
.
.
.
}

@ConditionalOnBean(name = "yoni")
@Service
public class b {
.
.
.
}

@Service
public class d {
    @Autowired
    private ApplicationContext applicationContext;

    public void addYoni(){
        ConfigurableApplicationContext configContext = (ConfigurableApplicationContext) applicationContext;
        DefaultListableBeanFactory beanRegistry = (DefaultListableBeanFactory) configContext.getBeanFactory();
        beanRegistry.registerSingleton("yoni", yoni());
        
        // What Should be written here to cause Spring to check and to inject the under-conditions classes into the application context?
    }
    
    public Rab yoni() {
        Rab rab = new rab();
        .
        .
        .        
        return rab;  
    } 
}

Finally, I found a way to do so. It required to look for the classes with the annotation ConditionalOnBean and create a bean from them. Here is the code (class d in the question):

@Service
public class d {
    @Autowired
    private ApplicationContext applicationContext;


    public void addC(){
        ConfigurableApplicationContext configContext = (ConfigurableApplicationContext) applicationContext;
        DefaultListableBeanFactory beanRegistry = (DefaultListableBeanFactory) configContext.getBeanFactory();
        beanRegistry.registerSingleton("yoni", yoni());

        ClassPathScanningCandidateComponentProvider componentProvider =
                new ClassPathScanningCandidateComponentProvider(false);
        componentProvider.addIncludeFilter(new AnnotationTypeFilter(ConditionalOnBean.class));
        Set<BeanDefinition> candidateComponents = componentProvider.findCandidateComponents("base.project.package");
        candidateComponents.forEach(beanDefinition -> {
            String className = beanDefinition.getBeanClassName().substring(beanDefinition.getBeanClassName().lastIndexOf('.') + 1);
            String beanName = Character.toLowerCase(className.charAt(0)) + className.substring(1);
            if (!applicationContext.containsBean(beanName))
            {
                Map<String, Object> annotationAttributes = ((ScannedGenericBeanDefinition) beanDefinition).getMetadata().getAnnotationAttributes(
                        ConditionalOnBean.class.getName());
                String[] beansDependsOn = (String[]) annotationAttributes.getOrDefault("name", new String[]{});
                if ((beansDependsOn.length == 1) && (beansDependsOn[0].contentEquals("yoni")) {
                    try {
                        beanRegistry.createBean(Class.forName(beanDefinition.getBeanClassName()));
                    } catch (ClassNotFoundException e) {
                        log.error("Failed to init the class : [" + beanDefinition.getBeanClassName() + "]\n", e);
                        throw new RuntimeException(e);
                    }
                }

            }
        });
    }

    public Rab yoni() {
        Rab rab = new rab();

        return rab;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM