如何处理库所需的Spring bean?

时间:2018-01-02 20:14:15

标签: java spring

我通过将一些共享组件(Web服务客户端)移动到库中来重构使用Spring的应用程序。组件无法自行运行,因此仍需要使用该库的应用程序中的某些bean。这是什么最好的做法?

我创建了一个@Configuration类,因此应用程序只需要@Import它来使用该库,但是应用程序还需要提供一个Jackson ObjectMapper和一个包含如何联系web服务的Settings对象。我将ObjectMapper和Settings bean自动装配到库中使用的各种bean中。应用程序通过将Client注入其代码并调用它来使用该库。

这样可行,但我不确定它是不是正确的风格。在IntelliJ IDEA中,当我开发库时,它抱怨库注入的bean不存在红色下划线,这是真的,它们不存在。但通常当我看到所有无法解决的文件都是红色的时候,这告诉我也许我没有采用正确的方式。

库需要与使用Spring 3和5的应用程序一起使用。如果某个库不适合定义自己的应用程序(例如,因为应用程序已经有杰克逊)和"专有"像Settings对象一样的bean?

2 个答案:

答案 0 :(得分:2)

你的问题有点宽泛,但希望我能给你一个正确方向的暗示。

  

组件无法自行运行,因此仍需要使用该库的应用程序中的某些bean。这是什么最好的做法?

  • 首先:这个组件应该使用接口而不是一些具体的bean。
  • 第二:如果你有一个可重用的库,那么这个典型需要一些配置,这不能成为库本身的一部分,因为它依赖于使用该库的应用程序
  • 第三:因为第二个(和第一个):您的库不应该基于任何形式的自动布线,而是您的库应该基于显式(或默认)配置。

这解决了这个问题。在应用程序中使用库的接口和显式配置。以及向lib添加所需配置的良好文档。

答案 1 :(得分:1)

使用来自@Kayaman和@Ralph的灵感,我认为将Spring作为直接从应用程序上下文中使用的库的一部分公开是不合适的。我现在意识到这也不合适,因为图书馆可能会定义重复的私人"它不想暴露的豆子。我在思考它。如果我想使用Spring,我发现我可以这样做:

public class Factory {
    public static Client createClient(ObjectMapper mapper, Settings settings) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        beanFactory.registerSingleton("mapper", mapper);
        beanFactory.registerSingleton("settings", settings);
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(beanFactory);
        ctx.registerBean(ClientConfiguration.class);
        ctx.refresh();
        return ctx.getBean(Client.class);
    }
}

基本上,将Spring用作实现细节是可以的。由于我的配置只暴露了一个bean,因此它作为工厂方法是有意义的。在应用程序中,我将创建一个这样的方法:

@Bean public Client makeClient(ObjectMapper mapper, Settings settings) {
    return Factory.createClient(mapper, settings);
}

当然,Bean方法将从应用程序的上下文中注入ObjectMapper和Settings,或者可以是ObjectMapper / Settings的内联构造函数。

相反,我决定的是因为客户端没有足够的bean而且没有一个是懒惰的,我只是完全删除了Spring注释,并且手动构建了对象图,几乎和spring上下文一样多。现在,该库的好处是在运行时根本不需要Spring,在一个假定的非Spring应用程序中。