spring aop
软件系统通常由多个组件构成,每个组件负责一个特定的功能领域。但是,这些组件也经常承担它们的核心功能之外的额外责任。系统服务(例如日志、事务管理和安全性)经常发现自己跑到了别的组件的领域里,而这些组件的核心职责是其他事情。结果就是所谓的“代码纠缠”,或者更简单点儿说“一团糟”。面向方面编程是一种试图解决这个问题的编程技术,它把关注点的隔离提升为核心的编程概念。
使用 aop 时,仍然是在一个地方定义系统的公共功能,但是可以声明性地定义 如何 和 在哪里 应用这个功能。如果对横切关注点(例如日志和事务管理)进行了模块化,那么不用修改每个单独的类,就可以向代码中添加新特性。这类模块化的关注点称作 方面。
您知道么?
可以在任何 java? 企业版(j2ee) 服务器中使用 spring 框架的功能。而且,还可以调整它的大多数功能,使其适合不受控环境。spring 的中心焦点就是支持不被束缚在特定 j2eee 服务上的可重用业务和数据访问对象。可以跨 j2ee 环境(web 或企业 javabean(ejb))、独立应用程序、测试环境等等重用这类对象,而不会有任何麻烦。
以一个企业应用程序为例。这类应用程序通常要求类似于安全性和事务支持的服务。显然,可以把这些服务的支持直接编写到要求服务的每个类当中,但是更希望能够不必为大量事务性上下文编写同样的事务处理代码。如果使用 spring aop 进行事务处理,那么可以声明性地安排适当的方法调用,而不必逐个安排。
spring aop 提供了几个方面,可以为 javabean 声明事务。例如,transactionproxyfactorybean 是个方便的代理类,能够拦截对现有类的方法调用,并把事务上下文应用到事务 bean。在下面的示例中会看到这个类的实际应用。
hibernate
spring 框架提供了对 hibernate、jdo 和 ibatis sql maps 的集成支持。spring 对 hibernate 的支持是第一级的,整合了许多 ioc 的方便特性,解决了许多典型的 hibernate 集成问题。框架对 hibernate 的支持符合 spring 通用的事务和数据访问对象(dao)异常层次结构。
spring 为使用选择的 or 映射层来创建数据访问应用程序提供了支持。因为所有东西都设计成一组可重用 javabean,所以不管选择什么技术,都能以库的格式访问大多数 spring 的 or 映射支持。 applicationcontext 或 beanfactory 内部的 or 映射的好处是简化了配置和部署。
hibernate 是 java 平台上一个功能全面的、开源的 or 映射框架。hibernate 支持开发符合常规 java 理念的持久性类 ―― 包括关联、继承、多态、复合以及 java 集合框架。hibernate 查询语言(hql)被设计成 sql 的一个微型面向对象扩展,它是对象和关系世界之间的桥梁。hibernate 也支持用原始 sql 或基于 java 的标准和示例查询表达查询。hibernate 使用 xml(*.hbm.xml) 文件把 java 类映射到表,把 javabean 属性映射到数据库表。
通过 jdbc 技术,支持所有的 sql 数据库管理系统。hibernate 与所有流行的 j2ee 应用程序服务器和 web 容器都很好地集成。
实际示例
一个银行应用程序示例可以让您自己看到 spring aop 和 hibernate 一起工作有多么好。银行帐户用例允许用户 (customer) 在一个事务中打开一个或多个银行帐户。用户可以申请多个银行帐户,可以选择是支票帐户类型或者是储蓄帐户类型。
应用程序数据库(cloudscape?)容纳所有客户和帐户信息。在这个例子中,假设在 customer 和 account 类之间存在 1:n 的关联。在实际生活场景中,关联可能需要按 m:n 建模,才能支持联合帐户。
由于用户必须可以在一个事务中申请多个帐户,所以首先要为数据库交互实现一个 doa 模式。然后要设置 spring aop 的 transactionproxyfactorybean,让它拦截方法调用并声明性地把事务上下文应用到 doa。
hibernate 实践
在 spring 框架中,像 jdbc datasource 或 hibernate sessionfactory 这样的资源,在应用程序上下文中可以用 bean 实现。需要访问资源的应用程序对象只需通过 bean 引用得到这类预先定义好的实例的引用即可(这方面的更多内容在 下一节中)。在清单 1 中,可以看到示例银行应用程序的一段摘录:xml 应用程序上下文定义显示了如何设置 jdbc datasource,并在上面放一个 hibernate sessionfactory。
清单 1. jdbc datasource 和 hibernatesessionfactory 连接
<!-- datasource property -->
<bean id="exampledatasource"
class="org.apache.commons.dbcp.basicdatasource">
<property name="driverclassname">
<value>org.apache.derby.jdbc.embeddeddriver</value>
</property>
<property name="url">
<value>jdbc:derby:springexample;create=true</value>
</property>
</bean>
<!-- database property -->
<bean id="examplehibernateproperties"
class="org.springframework.beans.factory.config.propertiesfactorybean">
<property name="properties">
<props>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop
key="hibernate.dialect">net.sf.hibernate.dialect.derbydialect</prop>
<prop
key="hibernate.query.substitutions">true 't', false 'f'</prop>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.c3p0.minpoolsize">5</prop>
<prop key="hibernate.c3p0.maxpoolsize">20</prop>
<prop key="hibernate.c3p0.timeout">600</prop>
<prop key="hibernate.c3p0.max_statement">50</prop>
<prop
key="hibernate.c3p0.testconnectiononcheckout">false</prop>
</props>
</property>
</bean>
<!-- hibernate sessionfactory -->
<bean id="examplesessionfactory"
class="org.springframework.orm.hibernate.localsessionfactorybean">
<property name="datasource">
<ref local="exampledatasource"/>
</property>
<property name="hibernateproperties">
<ref bean="examplehibernateproperties" />
</property>
<!-- or mapping files. -->
<property name="mappingresources">
<list>
<value>customer.hbm.xml</value>
<value>account.hbm.xml</value>
</list>
</property>
</bean>
清单 1 显示了如何为示例应用程序数据库(是 cloudscape)配置数据源 bean (exampledatasource)。exampledatasource 被连接到 spring hibernate 的 sessionfactory。请注意 *.hbm.xml 指定了示例应用程序的 or 映射文件。
数据源和会话工厂设置好之后,下一步就是在 dao 中连接,在 customerdaoimpl 示例中,要使用 sessionfactory。接下来,插入 spring 的 transactionproxyfactorybean,它会拦截对应用程序的 customerdaoimpl 对象的方法调用,并声明性地在它上面应用事务。
在 清单 2 的这个示例中,customerdaoimpl 类的 addcustomer 方法是作为事务的一部分执行的,有一个事务属性 propagation_required。这个属性等价于 ejb 容器的 tx_required。如果想让这个方法一直在事务中运行,可以使用 propagation_required。如果事务已经在运行,那么 bean 方法会加入事务,否则 spring 的轻量级事务管理器会启动一个事务。如果想在调用组件服务时总是启动新事务,可以使用 propagation_requires_new 属性。
应用程序的连接完成之后,现在来进一步查看源代码。
分析这个!
如果以前没这么做过,那么请 下载这篇文章的源代码。把源 zip 文件释放到计算机中的任何位置上,例如 c:/。会创建一个叫作 springprojectpart2 的文件夹。src/spring 文件夹包含示例应用程序的 hibernate 映射文件和 spring 配置文件。src/springexample/hibernate 文件包含应用程序的源代码。
在这里会发现两个类,即 customer 和 account,它们用 hibernate 映射文件映射到两个表。customer 类代表客户信息,account 代表客户的帐户信息。正如前面提到的,我把这两个类按照 1: n 关系进行建模,即一个 customer 可以拥有多个 account。清单 3 显示了 customer 对象的 hibernate 映射文件。
清单 3. customer 对象的 hibernate 映射文件
<?xml version="1.0"?>
<!doctype hibernate-mapping public
"-//hibernate/hibernate mapping dtd 2.0//en"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class
name="springexample.hibernate.customer"
table="tbl_customer"
dynamic-update="false"
dynamic-insert="false">
<id
name="id"
column="customer_id"
type="java.lang.long"
unsaved-value="-1"
>
<generator class="native">
</generator>
</id>
闽公网安备 35060202000074号