在Spring JavaConfig中,bean返回类型应该是接口还是实现?

时间:2015-11-13 13:50:58

标签: java spring spring-java-config

当我通过XML配置实现DataSource(例如HikariCP)的类时,它看起来像这样:

<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close"/>

根据Spring Reference manual,JavaConfig中的相应内容是:

@Bean (destroyMethod = "close")
public DataSource dataSource () {
    return new HikariDataSource();
}

为什么我们在JavaConfig中返回接口类型,特别是在这种情况下,DataSource没有close()方法,但实现确实如此(并且Spring确实设法找到了close()方法)?

我无法发现应用程序在此配置方法与使用实现类型之间的行为有任何不同:

@Bean (destroyMethod = "close")
public HikariDataSource dataSource () {
    return new HikariDataSource();
}

即使考虑自动装配,这也不是问题,因为两种返回类型都适用于DataSource实例变量。 那么返回的正确类型是什么(如果有正确的&#39;那么),为什么?

2 个答案:

答案 0 :(得分:2)

  

我发现应用程序之间的行为没有任何区别   这种使用实现类型的配置方法

你说得对,没有任何区别,因为在这两种情况下,最终返回的是new HikariDataSource();,即HikariDataSource类的对象。

您的第一个案例是更具可扩展性,因为将来您可以返回DataSource的其他一些实现而不更改返回类型。或者,您可以更新该方法以实现Factory设计模式,以根据情况返回DataSource的大量实现。

  

那么返回的正确类型是什么(如果有正确的类型),   为什么?

实际上没有正确的方法,它完全取决于开发人员但是&#34;程序接口&#34; 总是很好的设计。在你的情况下,因为你正在返回一些东西,所以它不会有太大的区别,但你仍然应该使用public DataSource dataSource ()

当您可以创建接受某个参数的方法时,编程到界面特别有用,假设public void dataSource (DataSource ds),在这种情况下您可以传递DataSource的任何实现,因此它是一个很好的设计因为它是可扩展的

Read more about program to interface

另外,我建议阅读Factory design pattern,这是一个良好的界面程序示例。

答案 1 :(得分:1)

您应该返回通用实现。

这就是原因:

首先,你是对的。如果您返回impl,您仍然可以自动装配接口。所以你可以做到,然后:

@Autowire Datasource ds;

但是,你不能这样做。您无法返回数据源并自动装配HikariDataSource。

为什么这很重要?

您不希望您的实现依赖于特定的实现。例如:

您编写了Appcode,所有代码都依赖于HikariDataSource。由于这是一个数据源,假设你有400个daos实现了使用它并使用该类的实现特定细节。现在,如果你改变那个impl,你所有的客户都会破产。你将有一段时间让事情再次发挥作用。每当你需要改变它时,这将重复出现(请注意,probs不会像数据源一样经常发生)。

现在返回接口或基类会阻止客户端依赖于特定于实现的详细信息。之后您可以快速切换数据源。只要您实现数据源接口,一切都将继续有效。

下一个:测试。 您希望为测试提供不同的东西(让我们说数据源)。你真的想为你的测试启动一个数据库,而内存数据库就足够了吗? 现在在DAO测试中,如果依赖于IMPL,则无法针对通用数据源(InMemoryDataSource)进行测试。如果返回界面,则可以使用不同的测试配置来简化设置。

我希望这有意义/有帮助。

干杯,

阿图尔