使用 Spring Bean 连接数据库对象

Posted

技术标签:

【中文标题】使用 Spring Bean 连接数据库对象【英文标题】:Wiring Database Object with Spring Bean 【发布时间】:2016-12-24 12:14:47 【问题描述】:

在 Spring in Action 一书中,有一个 Spring Bean 的例子。它使用Compact Disc 类比。当应用程序需要"The Beatles" album 时,它会创建"The Beatles" album bean 以及其他相册。

    如果数据库中有n 相册,那么我应该创建n 相册bean 吗? 如果不是,n的相册在应用中是如何表示的?它只是一个 POJO 域模型(不是 bean)吗? 使用 Spring Bean 的真正用例是什么?

【问题讨论】:

【参考方案1】:

如果我是你,我不会将光盘类比为 Spring bean,尤其是关于你后来的问题。很明显,任何 Java 对象都可以在 Spring 中声明为 bean,无论您使用的是 XML 配置还是 Java 配置。

假设我有这两个类:

public class Foo 

    private String s;

    private Bar bar;

    // getters & setters



public class Bar 

    private int i;

    // getter & setter


我可以通过在 XML 配置文件中声明前者来使前者成为 Spring Bean:

<bean id="foo" class="demo.Foo">
    <property name="s" value="Hello, World!" />
    <property name="bar">
        <bean class="demo.Bar">
            <property name="i" value="10" />
        </bean>
    </property>
</bean>

现在,用这两行代码:

ApplicationContext ctx = new ClassPathXmlApplicationContext("app.xml");
Foo foo = ctx.getBean(Foo.class);

可以检索配置的 foo 对象,并设置其所有属性,包括bar。这是 Spring 的核心用例,即让您配置应用程序的构建块如何在运行时解决它们的依赖关系。最初 Spring 只关注代码之外的配置,但现在关注点略有变化,比如组件扫描和 Java 配置……

无论如何,以这个简短的例子结束,以下代码行将打印 10:

System.out.println(foo.getBar().getI());

在这个例子中,我使用了 Foo 和 Bar,但它也可以是一个 Web 服务,一个实现一些业务逻辑的服务,一个数据库,一个 ORM 外观,一个模板引擎,一个线程池,任何东西......但是主要是处理数据对象的组件,而不是数据对象本身,尽管这是完全可能的。

现在返回您的用例,在 Spring 应用程序中,如果我正在编写带有数据库的 Web 应用程序,我通常会拥有这些组件:控制器(Web 边界)、服务(用于业务逻辑)、一个存储库(用于查询),当然还有一个数据源。我不会在这里深入研究太多细节(例如,没有声明性事务)。请注意,使用此配置,我的 Java 代码中不会编译任何特定的数据提供程序,它仍保留在配置中:

<bean id="cdController" class="demo.compactdisc.CdController">
    <property name="cdService" ref="cdService" />
</bean>

<bean id="cdService" class="demo.compactdisc.CdServiceImpl">
    <property name="cdRepository" ref="cdRepository" />
</bean>

<bean id="cdRepository" class="demo.compactdisc.CdRepositoryImpl">
    <property name="dataSource" ref="dataSource" />
</bean>

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/test"/>
    <property name="username" value="test"/>
    <property name="password" value="s3cr3t"/>
</bean>

使用您的域,存储库会将光盘从数据库返回给服务,将服务返回给控制器,将控制器返回给用户。光盘不会被描述为 Spring bean,但肯定是来自实际 Spring bean 的参数和返回值。

【讨论】:

那么适合Spring Beans的POJO标准是什么? 确实没有标准。对于所有 Spring 关心的类,该类可以声明为 final,没有默认构造函数。 POJO 与如何开发一个类有关。 POJO 是松散地遵循 JavaBeans 规范的简单对象。 Spring bean 是在 IoC 容器中声明并可以从中检索的任何 对象。 FooBar 是 POJO,被声明为 Spring bean。 我的意思是,什么时候 POJO 适合 Spring Bean?示例:在文档中 DataSource 适用于 Spring Bean,但域模型不适用。 用技术术语来说,POJO 总是合适的。然而,在设计方面,域对象几乎永远不会用作 bean,除非您将其声明为原型(使用 scope 属性)。我认为您混淆了 POJO 和域对象。 POJO 讲述了一个类的开发方式,领域对象讲述了这个 POJO 在您的应用程序中的作用。为简单起见,您应该考虑 Spring bean 是可以在应用程序中实现为单例的对象。 Spring bean 默认是单例的(这是默认的scope),所以从一开始就很简单。 这是一种看待事物的方式。请注意,request 和 session 用于 Web 应用程序,globalSession 用于 portlet。我会将问题简化为:“我的对象是单例还是我的对象是此模板对象的原型?”但是,是的,你已经掌握了窍门。【参考方案2】:

如果数据库中有 n 个专辑,那么我应该创建 n 个专辑 bean 吗?

我认为不会。如果有 n 个专辑,那么将它们全部明确包含在您的 App.config 文件中会非常麻烦,如果这就是您所指的;但你可以。您可能会添加一个 AlbumService (@Service) @Bean 和关联的 @Repository 来处理从数据库中写入和检索它们。

如果不是,那n张专辑如何在应用程序中表示?难道只是 POJO 域模型(不是 bean)?

您可以拥有一个具有专辑属性的 Album @Entity bean。当您保存相册时,您需要设置属性,而不是让单个组件实现公共接口。您的数据库中将有 n 个专辑。例如,如果您只需要检索 Beatles 的一张专辑,您可以根据专辑名称进行查询。如果你想要它们,你可以做albumService.findAll();并得到一个容器。

使用 Spring Bean 的真正用例是什么?

Spring 是 Spring Bean 的真正用例。根据Spring IoC Container Reference:

在 Spring 中,构成应用程序主干的对象和 由 Spring IoC 容器管理的称为 bean。一颗豆子 是一个被实例化、组装和以其他方式管理的对象 一个 Spring IoC 容器。否则,豆子只是众多豆子中的一种 应用程序中的对象。 Beans,以及它们之间的依赖关系, 反映在容器使用的配置元数据中。

我无法提供比文档中包含的内容或此 answer 中给出的更好的答案。

【讨论】:

那么适合Spring Beans的POJO标准是什么? @YosuaLijantoBinar,请参阅我在答案中提供的链接中的this section。您可能“[n]注意到这个类没有什么特别之处,它是一个 POJO,不依赖于容器特定的接口、基类或注释。” 我的意思是,什么时候 POJO 适合 Spring Bean?示例:在文档中 DataSource 适用于 Spring Bean,但域模型不适用。【参考方案3】:

    您只需要拥有一个 Album 类并将其注释为 @Component 或通过 xml 进行。

    术语beanPOJO 可以互换。根据Spring in action 4rd edition,Spring 努力成为一个非侵入性的框架。

(...)基于 Spring 的应用程序中的类通常没有 表明它们正在被 Spring 使用。在最坏的情况下,一个类可能会使用 Spring 的注释之一进行注释,但否则它就是一个 POJO

虽然 Spring 大量使用 bean 和 JavaBean 这两个词 当提到应用程序组件时,这并不意味着 Spring 组件 必须严格遵守 JavaBeans 规范。一个 Spring 组件可以是 任何类型的 POJO。

    用例是,您可以使用 Spring 依赖注入在运行时连接您的 bean,您的应用程序可以从 Spring 的简单性、可测试性和松散耦合方面受益。李>

简而言之,您所指的 Spring bean 只是在 Spring 应用程序的上下文中使用的 POJO。如果您使用 xml 映射而不是注解,您的类将只是另一个常规 Java 类,一个普通的旧 Java 对象。

【讨论】:

那么适合Spring Beans的POJO标准是什么?

以上是关于使用 Spring Bean 连接数据库对象的主要内容,如果未能解决你的问题,请参考以下文章

kafka连接数过多,转疯了!

Spring配置数据库连接池Druid

spring配置数据库连接池druid

spring 数据源 xml 中的 bean 创建是不是打开与数据库的连接?

spring annotation功能备注

使用Spring Reactive(R2DBC)与MSSQL连接,创建bean时出错