【问题标题】:Spring Java Configuration: Create Bean From Dynamic Class NameSpring Java 配置:从动态类名创建 Bean
【发布时间】:2014-05-13 14:17:28
【问题描述】:

我的情况是 bean 的类名可以由外部属性文件配置。用 XML 就可以了

  <bean id="myService" class="${app.serviceClass}" />

和属性文件

app.serviceClass=com.example.GreatestClassThereIs

我尝试使用 BeanFactoryPostProcessor 将其转换为 Java:

@Configuration
public class MyConfiguration implements BeanFactoryPostProcessor {

  @Value("${app.serviceClass}")
  private String serviceClassName;

  @Override
  public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    logger.warn("let's register bean of class " + serviceClassName + "...");
    GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
    beanDefinition.setBeanClassName(serviceClassName);

    BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
    registry.registerBeanDefinition("myService", beanDefinition);
    logger.warn("done " + beanDefinition);
  }
}

问题是Spring的生命周期还没有设置处理@ValueserviceClassNamenull。我如何获得那里的财产?

【问题讨论】:

  • 不确定您要达到的目标。你有一个@Configuration 类,它实际上是一个BeanFactoryPostProcessor。对我来说似乎很奇怪。定义 @Bean 并使用 Spring ClassUtils 创建该 bean 的实例。否则,使用 ${app.serviceClass} 注册 RootBeanDefinition 也可能有效。
  • @M.Deinum 好吧,我的问题中的来源只是这个问题的重要内容。我不想写可能会引起更多混乱的离题。我会检查你的两个建议。两者都会导致 Spring 在 bean 上执行 DI 等操作吗?
  • 一个 bean 无论如何构造都是一个 bean。
  • @SotiriosDelimanolis 我完全不明白所谓的重复问题是关于什么的。我可以看到一个答案建议使用BeanDefinitionRegistryPostProcessor,我还没有听说过,但其余的太混乱了,我什至无法争论我的问题是否重复;)
  • 没关系,我离题了。抱歉,已重新打开。

标签: spring configuration dependency-injection


【解决方案1】:

为什么不简单地在ApplicationContext 中定义一个新的Bean,方法是使用@Value 中的Class.forName() 注入@Configuration

所以是这样的:

@Configuration
public class MyConfiguration
{

     @Value("${app.serviceClass}")
     private String serviceClassName;

     @Bean
     public Object myService()
     {
          return Class.forName(serviceClassName).newInstance();
     }
}

由 sjngm 编辑(为了比评论更好的可读性):

     @Bean
     public MyInterface myService()
     {
        Class<?> serviceClass = Class.forName(serviceClassName);
        MyInterface service = MyInterface.class.cast(serviceClass.newInstance());
        return service;
     }

【讨论】:

  • 我猜想在针对接口实现时,myService 的返回类型可以是接口。这对于这个bean在其他地方的DI很重要。
  • 应用启动时如果没有serviceClassName怎么实现?
猜你喜欢
  • 2013-11-16
  • 2021-05-02
  • 2012-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多