【问题标题】:Spring @Bean autowire() - fails the second (?) timeSpring @Bean autowire() - 第二次(?)失败
【发布时间】:2015-09-02 23:34:09
【问题描述】:

好的,所以,我有一个创建两个 bean 的配置类。它们的定义如下:

public class FileUploadConfiguration {

    public static final String UPLOAD_PREFIX = "file.upload";

    @Bean(name = "fileService", autowire = Autowire.BY_TYPE)
    @DependsOn("fileUploadPaths")
    @Autowired
    public CRUDFileService fileService(@Qualifier("fileUploadPaths") PrefixedPropertyFactoryBean fileUploadPaths) throws Exception {
        Map<String, String> paths = Maps.fromProperties(fileUploadPaths.getObject());
        return new CRUDFileService(File.class.getName(), paths);
    }

    @Bean(name = "fileUploadPaths")
    public PrefixedPropertyFactoryBean fileUploadPaths(Environment environment) {
        PrefixedPropertyFactoryBean fileUploadPaths = new PrefixedPropertyFactoryBean();
        fileUploadPaths.setPrefix(UPLOAD_PREFIX);
        fileUploadPaths.setLocations(ResourceUtils.getActiveResources(environment));
        return fileUploadPaths;
    }
}

如果我在两个实例中都设置断点,流程如下:

1) fileUploadPaths 已实例化,对我来说它看起来是正确的。

2) fileService 被实例化,但是通过 FileUploadConfiguration bean 创建的 postProcessPropertyValues ......这对我来说似乎很奇怪。

3) 之后,我得到一个异常,因为似乎 Spring 尝试再次创建 fileService,但现在通过 createBean,并且由于某种原因 @Qualifier关于参数定义似乎被忽略了。

线程“main”中的异常 org.springframework.beans.factory.UnsatisfiedDependencyException: 创建类中定义的名称为“fileService”的 bean 时出错 x.y.z.FileUploadConfiguration:表示不满足的依赖关系 通过类型索引为 0 的构造函数参数 [a.b.c.PrefixedPropertyFactoryBean]:不明确的工厂方法参数 类型 - 您是否将正确的 bean 引用指定为工厂方法 论据?在 org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:735) 在 org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:464) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1119) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1014) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476) 在 org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303) 在 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) 在 org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299) 在 org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194) 在 org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:755) 在 org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757) 在 org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480) 在 org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118)

注意:如果我将 fileService 定义更改为以下内容,则会解决此问题:

@Bean(name = "fileService")
@DependsOn("fileUploadPaths")
@Autowired
public CRUDFileService fileService(@Qualifier("fileUploadPaths") PrefixedPropertyFactoryBean fileUploadPaths, AutowireCapableBeanFactory factory) throws Exception {
    Map<String, String> paths = Maps.fromProperties(fileUploadPaths.getObject());
    CRUDFileService crudFileService = new CRUDFileService(File.class.getName(), paths);
    factory.autowireBean(crudFileService);
    return crudFileService;
}

所以,我没有让 Spring 通过 @Bean(autowire = Autowire.BY_TYPE) 自动装配我的 bean,而是简单地自动装配 AutowireCapableBeanFactory 并自动装配 CRUDFileService 自己做豆子。

我的问题是:为什么会发生这种行为?我使用 @Bean(autowire = Autowire.BY_TYPE) 正确吗?我以前就这样用过它,它的作用就像一个魅力,只是我没有像我用这个那样自动装配 bean 方法参数。

【问题讨论】:

  • 只是为了澄清一下 - PrefixedPropertyFactoryBean 是 Spring Factory bean 吗?
  • @BijuKunjummen 是的 - 它扩展了 AbstractFactoryBean.

标签: java spring dependency-injection autowired


【解决方案1】:

我看到的问题是您试图将 Spring FactoryBean 作为依赖项注入另一个 bean。 FactoryBean 很特别,它是 bean 的工厂,生成的 bean 就是您应该注入到其他对象中的内容。

因此,假设您在 CRUDFileService 中的依赖项是 Properties 类而不是 FactoryBean,如果您要尝试此操作,它应该可以正常工作:

public class FileUploadConfiguration {

    public static final String UPLOAD_PREFIX = "file.upload";

    @Bean(name = "fileService", autowire = Autowire.BY_TYPE)
    @Autowired
    public CRUDFileService fileService(@Qualifier("fileUploadPaths") Properties fileUploadPaths) throws Exception {
        Map<String, String> paths = Maps.fromProperties(fileUploadPaths);
        return new CRUDFileService(File.class.getName(), paths);
    }

    @Bean(name = "fileUploadPaths")
    public PrefixedPropertyFactoryBean fileUploadPaths(Environment environment) {
        PrefixedPropertyFactoryBean fileUploadPaths = new PrefixedPropertyFactoryBean();
        fileUploadPaths.setPrefix(UPLOAD_PREFIX);
        fileUploadPaths.setLocations(ResourceUtils.getActiveResources(environment));
        return fileUploadPaths;
    }
}

【讨论】:

  • 为什么删除autowire(因此默认为Autowire.NO)并保留PrefixedPropertyFactoryBean作为参数类型有效?
  • 嘿@BijuKunjummen,你说的很有道理——我应该在创建bean时注入工厂创建的对象,而不是工厂本身。但这并没有解决,我现在得到了相同的异常,但使用了属性:通过构造函数参数表示的不满足的依赖关系,索引为 0,类型为 [java.util.Properties]:不明确的工厂方法参数类型 - 你指定了正确的 bean 引用作为工厂方法参数?
猜你喜欢
  • 1970-01-01
  • 2013-12-17
  • 2020-10-02
  • 2011-03-22
  • 1970-01-01
  • 1970-01-01
  • 2015-01-23
  • 2020-08-31
  • 2015-09-01
相关资源
最近更新 更多