【问题标题】:Spring Prototype-Bean Provider without @Autowired没有 @Autowired 的 Spring Prototype-Bean Provider
【发布时间】:2017-10-10 09:14:24
【问题描述】:

我有一个原型 Bean,它由带有 Provider 的单例 bean 实例化:

@Component
@Scope("prototype")
class MyPrototype {}

@Component
class MySingleton {
    @Autowired
    javax.inject.Provider<MyPrototype> prototypeFactory;
}

这很好用,但我们的公司规则规定@Autowired 是不允许的;常见的模式是@Resource(SingletonBeanClass.BEAN_ID)

是否可以通过这种方式注释 Provider 以便 Spring 查找可以创建它?

我知道我可以使用 @Lookup 或单例工厂 bean 添加工厂方法,但我更喜欢 Provider

编辑: 我没有让它以这种方式工作,最后不得不编辑spring.xml;详情见下文。

【问题讨论】:

  • 出于好奇,为什么不允许@Autowired
  • @araknoid 我认为他们希望直接控制实例化的类......对我来说没有多大意义,但我无法争论这个。
  • 是否允许@Inject(来自 javax.inject)?
  • 如果你有 bean 注入的 XML 配置文件,可以通过 XML 配置
  • @MystyxMac 至少自动 QA 检查没有抱怨,试图摆脱这个 ;)

标签: java spring


【解决方案1】:

由于你有一个 XML 配置文件,你可以通过 XML 来配置它,方式如下:

<bean id="myPrototype" class="some.package.MyPrototype" scope="prototype" />

<bean id="mySingleton" class="some.package.MySingleton">
    <lookup-method name="getPrototypeFactory" bean="myPrototype "/>
</bean>

这样,您必须使用getPrototypeFactory() 访问myPrototype,而不是直接访问该属性。您甚至可以删除这 2 个类上的注释。

更多细节可以看下面的博文Injecting a prototype bean into a singleton bean

【讨论】:

  • 这就是我最终做的;我自己写了一个答案,因为它有点复杂。不过,将您的设置为“已回答”。
  • 哦,我刚刚注意到,你不能使用ref,否则原型 bean 只会为单例创建一次,但我必须在单例生命周期内实例化几次。
  • @daniu 更正了我的答案。粘贴了错误的配置并添加了一些额外的细节。
【解决方案2】:

供参考,如果有人通过 Google 发现此内容:

我最终需要在spring.xml 中声明它。我试过@Lookup,但由于prototype-bean引用了另一个prototype-bean,即使这样也没有用。

原来是这样recommended here, 但它不起作用:

@Component("proto1")
@Scope("prototype")
class MyPrototypeBean1 {
    @Lookup(value="proto2")
    protected MyPrototypeBean2 createBean2() { return null; }
}

@Component("proto2")
@Scope("prototype")
class MyPrototypeBean2 {
}

@Component("singleton")
class MySingleton {
    @Lookup(value="proto1")
    protected MyPrototypeBean1 createBean1() { return null; }
}

这会导致在尝试创建“innerBean...”时出现错误消息“无法将 @Lookup 应用于没有相应 bean 定义的 bean”。

我认为这是由于上面链接中引用的“无法在工厂方法返回的 bean 上替换查找方法,我们无法为它们动态提供子类”。

所以我最终在spring.xml 中做了什么:

<bean name="proto2" class="my.package.PrototypeBean2" />
<bean name="proto1" class="my.package.PrototypeBean1" >
    <lookup-method name="createBean2" bean="proto2" />
</bean>
<bean name="singleton" class="my.package.SingletonBean" >
    <lookup-method name="createBean1" bean="proto1" />
</bean>

这行得通。

对于单元测试,我必须对各个类进行子类化:

class SingletonUnitTest {
    @Mock
    MyPrototypeBean1 bean1;
    @InjectMocks
    DummySingleton sut;

    @Before public void setBean1() {
        sut.bean = bean1;
    }

    static class DummySingletonBean extends MySingeton {
        MyPrototypeBean1 bean;
        protected MyPrototypeBean1 createBean1() {
            return bean;
        }
    }
}

【讨论】:

    猜你喜欢
    • 2021-01-07
    • 1970-01-01
    • 2015-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多