我已经将代码从Spring的XML配置迁移到Java配置。我一切正常,但是我有一个关于如何实现原型bean的问题-主要是,当我在做什么的时候,这是最好的方法吗?不知何故它感觉不对!

我这样写了bean类:

@Component
@Scope("prototype")
public class ProtoBean {
    ...
}


然后使用Bean-尽管确实有效,但这是我不确定的部分:

@Component
public class BeanUser implements ApplicationContextAware {
    ApplicationContext context;

    @Override
    public void setApplicationContext(ApplicationContext context)throws BeansException
    {
        this.context = context;
    }

    public void getProtoBean() {
         ProtoBean protoBean = context.getBean(ProtoBean.class);
    }
}


这为我提供了一个原型bean,并且在单元测试中,我只是模拟了该上下文,并使用模拟程序调用了setApplicationContext,并使模拟程序的getBean调用返回了一个模拟ProtoBean。一切都很好。

我通过使用工厂在XML中进行了此操作,但效果似乎不太好,所以这就是我要结束的地方。但是,没有上下文,有没有办法做到这一点?还是更好的方法?

谢谢!

最佳答案

我不认为Spring XML与基于Java的配置有太大关系,而是匹配的依赖范围之一。由于Spring在创建时只能对单例作用域的bean进行依赖项注入,因此您必须按需查找原型作用域的bean。当然,当前的bean查找方法有效,但是会创建对ApplicationContext的依赖。我可以提出其他几种可能性,但问题的根源实际上是生产ProtoBean涉及的是什么,以及您应该接受哪些折衷。

您可以使BeanUser本身具有原型作用域,这将使您可以将ProtoBean作为成员加入。当然,需要权衡的是您现在在BeanUser的客户端上遇到了相同的问题,但是有时这不会成为问题。

另一条路径可能是使用类似单例作用域的ProtoBeanFactory来提供ProtoBean实例,并在ProtoBeanFactory中隐藏依赖项查找。

最后,您可以使用带作用域的代理bean有效地隐藏工厂。它使用AOP来做到这一点,并且并不总是向他人清楚您将使用哪种伏都教。对于XML,您将在bean声明上使用<aop:scoped-proxy/>。对于注释,您将使用:

@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS, value = "prototype")

08-05 15:43