如果条件注解的值也是配置在apollo上,可能会出现依赖条件注解的bean的其他bean,在项目拉取apollo配置时,就已经注入spring容器中,此时就算条件注解满足条件,则引用该条件注解bean的其他bean,也会拿不到条件注解bean。此时有2种方法解决,一种是在依赖条件注解bean的其他bean注入之前,先手动注册条件注解bean到spring容器中,其核心代码如下
@Component @Slf4j public class RefreshBeanFactory implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException { Config config = ConfigService.getConfig("order.properties"); List<String> basePackages = AutoConfigurationPackages.get(configurableListableBeanFactory); for (String basePackage : basePackages) { Set<Class> conditionalClasses = ClassScannerUtils.scan(basePackage, ConditionalOnProperty.class); if(!CollectionUtils.isEmpty(conditionalClasses)){ for (Class conditionalClass : conditionalClasses) { ConditionalOnProperty conditionalOnProperty = (ConditionalOnProperty) conditionalClass.getAnnotation(ConditionalOnProperty.class); String[] conditionalOnPropertyKeys = conditionalOnProperty.name(); String beanConditionKey = this.getConditionalOnPropertyKey(config,conditionalOnPropertyKeys); String conditionalOnPropertyValue = conditionalOnProperty.havingValue(); this.registerBeanIfMatchCondition((DefaultListableBeanFactory)configurableListableBeanFactory,config,conditionalClass,beanConditionKey,conditionalOnPropertyValue); } } } } private void registerBeanIfMatchCondition(DefaultListableBeanFactory beanFactory,Config config,Class conditionalClass, String beanConditionKey, String conditionalOnPropertyValue) { boolean isNeedRegisterBean = this.isNeedRegisterBean(config,beanConditionKey,conditionalOnPropertyValue); String beanName = StringUtils.uncapitalize(conditionalClass.getSimpleName()); if(isNeedRegisterBean){ this.registerBean(config,beanFactory,beanName,conditionalClass); } } public void registerBean(Config config,DefaultListableBeanFactory beanFactory, String beanName, Class beanClass) { log.info("registerBean->beanName:{},beanClass:{}",beanName,beanClass); BeanDefinitionBuilder beanDefinitionBurinilder = BeanDefinitionBuilder.genericBeanDefinition(beanClass); BeanDefinition beanDefinition = beanDefinitionBurinilder.getBeanDefinition(); setBeanField(config,beanClass, beanDefinition); beanFactory.registerBeanDefinition(beanName,beanDefinition); } private void setBeanField(Config config,Class beanClass, BeanDefinition beanDefinition) { ConfigurationProperties configurationProperties = (ConfigurationProperties) beanClass.getAnnotation(ConfigurationProperties.class); if(ObjectUtils.isNotEmpty(configurationProperties)){ String prefix = configurationProperties.prefix(); for (String propertyName : config.getPropertyNames()) { String fieldPrefix = prefix + "."; if(propertyName.startsWith(fieldPrefix)){ String fieldName = propertyName.substring(fieldPrefix.length()); String fieldVal = config.getProperty(propertyName,null); log.info("setBeanField-->fieldName:{},fieldVal:{}",fieldName,fieldVal); beanDefinition.getPropertyValues().add(fieldName,fieldVal); } } } } public boolean isNeedRegisterBean(Config config,String beanConditionKey,String conditionalOnPropertyValue){ if(StringUtils.isEmpty(beanConditionKey)){ return false; } String apolloConfigValue = config.getProperty(beanConditionKey,null); return conditionalOnPropertyValue.equals(apolloConfigValue); } private String getConditionalOnPropertyKey(Config config, String[] conditionalOnPropertyKeys){ if(ArrayUtils.isEmpty(conditionalOnPropertyKeys)){ return null; } String changeKey = null; for (String conditionalOnPropertyKey : conditionalOnPropertyKeys) { if(isConditionalOnPropertyKey(config,conditionalOnPropertyKey)){ changeKey = conditionalOnPropertyKey; break; } } return changeKey; } private boolean isConditionalOnPropertyKey(Config config,String conditionalOnPropertyKey){ Set<String> propertyNames = config.getPropertyNames(); if(!CollectionUtils.isEmpty(propertyNames) && propertyNames.contains(conditionalOnPropertyKey)){ return true; } return false; } }其次利用懒加载的思想,在使用条件注解bean时,使用形如下方法
Order order = (Order) SpringContextUtils.getBean("order"); 总结