java - 将任意对象注入(inject) Spring bean

标签 java spring spring-el

我的类包含几个返回一些Java对象的方法,即InputStream和OutputStream:

public class Provider {
    public InputStream getInputStream() { ... }
    public OutputStream getOutputStream() { ... }
}

另一方面,我有一个第三方类,其构造函数可以接受InputStream和OutputStream:

public class Consumer {
    public Consumer(InputStream is, OutputStream os) { ... }
}

问题是:如何将对 Provider 流的依赖注入(inject)到 Consumer bean 中?

这是我的 Spring XML 文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
     <bean id="provider" class="org.example.Provider" />
     <bean id="consumer" class="org.example.Consumer">
         <constructor-arg value="#{provider.inputStream}" />
         <constructor-arg value="#{provider.outputStream}" />
     </bean>
 </beans>

不幸的是,上述解决方案会导致以下错误:

Apr 01, 2014 10:54:59 AM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.FileSystemXmlApplicationContext@5f18cd5: display name [org.springframework.context.support.FileSystemXmlApplicationContext@5f18cd5]; startup
date [Tue Apr 01 10:54:59 MSK 2014]; root of context hierarchy
Apr 01, 2014 10:54:59 AM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from file [C:\Test\context.xml]
Apr 01, 2014 10:54:59 AM org.springframework.context.support.AbstractApplicationContext obtainFreshBeanFactory
INFO: Bean factory for application context [org.springframework.context.support.FileSystemXmlApplicationContext@5f18cd5]: org.springframework.beans.factory.support.DefaultListableBeanFactory@2d30be8c
Apr 01, 2014 10:54:59 AM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@2d30be8c: defining beans [provider,consumer]; root of factory hierarchy
Apr 01, 2014 10:54:59 AM org.springframework.beans.factory.support.DefaultSingletonBeanRegistry destroySingletons
INFO: Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@2d30be8c: defining beans [provider,consumer]; root of factory hierarchy
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'consumer' defined in file [C:\Test\context.xml]: Unsatisfied dependency expressed through constructor argument with index 0 of type [java.io.InputStream]: Could not convert constructor argument value of type [java.lang.String] to required type [java.io.InputStream]: Failed to convert value of type [java.lang.String] to required type [java.io.InputStream]; nested exception is java.lang.IllegalArgumentException: Could not retrieve InputStream for file [C:\Test\#{provider.getInputStream()}]: #{provider.getInputStream()} (File specified cannot be found)
        at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:565)
        at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:193)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:925)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:835)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:440)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
        at java.security.AccessController.doPrivileged(Native Method)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)
        at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:429)
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:728)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:380)
        at org.springframework.context.support.FileSystemXmlApplicationContext.<init>(FileSystemXmlApplicationContext.java:140)
        at org.springframework.context.support.FileSystemXmlApplicationContext.<init>(FileSystemXmlApplicationContext.java:84)
        at org.example.Launcher.main(Launcher.java:9)

这个错误日志看起来很奇怪,我真的很困惑发生了什么......

UPD:完整的堆栈跟踪已附加到帖子中。

最佳答案

您的配置将导致 Spring 想要调用:

 new com.example.Consumer("#{provider.inputStream}","#{provider.outputStream}");

...即Consumer(String,String)。但该构造函数不存在,因此失败。

您的错误消息无法将类型[java.lang.String]的构造函数参数值转换为所需类型[java.io.InputStream]表示。 “构造函数采用 InputStream,但你给了我 String

您需要要求 Spring 创建您的 Provider,然后调用该对象的方法来创建具有 Spring beans 的 InputStream 和 OutputStream。然后在您的 Consumer 中使用它们:

<bean id="provider"
     class="com.example.Provider" />

<bean id="inputStream"
   factory-bean="provider"
   factory-method="getInputStream"/>

<bean id="outputStream"
   factory-bean="provider"
   factory-method="getOutputStream"/>

<bean id="consumer" class="com.example.Consumer">
     <constructor-arg ref="inputStream" />
     <constructor-arg ref="outputStream" />
</bean>

您也可以内联执行此操作,例如

<bean id="consumer" class="com.example.Consumer">
     <constructor-arg>
         <bean factory-bean="provider" factory-method="getInputStream"/>
     </constructor-arg>
     <constructor-arg>
         <bean factory-bean="provider" factory-method="getOutputStream"/>
     </constructor-arg>
</bean>

基于Spring Expression Language docs (我没有测试过),以下方法也可能有效:

 <bean id="consumer" class="com.example.Consumer">
     <constructor-arg value="#{provider.getInputStream()}" />
     <constructor-arg value="#{provider.getOutputStream()}" />
 </bean>

...可能会帮助它:

<constructor-arg type="java.io.InputStream" value="#{provider.getInputStream()}" />

关于java - 将任意对象注入(inject) Spring bean,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22761673/

相关文章:

java - 只想填充二维数组的顶行和底行

java - 使用 Hadoop 0.20+ 生成多个输出文件

java - SQLiteDatabase.rawQuery(sql,new String[name,age,null]}) 一个参数无关紧要

java - 使用服务作为 "Factory"返回不同的 Bean 实现

java - Spring Boot @Scheduled 不起作用

spring - 如何检测嵌入式或独立的应用程序服务器?

java - 我可以阻止用户访问 Spring Security 中的某些内容的功能是什么

尝试使用 elvis 运算符编译表达式时,Spring SPEL 评估抛出 ArrayIndexOutOfBoundsException

java - 是否可以使用 th-field 来检索 Thymeleaf 中列表的值?

java - 基于 Java 的 Spring 配置中属性的模式匹配