总结如下:
Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource、TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分。
DataSource、TransactionManager这两部分只是会根据数据访问方式有所变化,比如使用Hibernate进行数据访问时,DataSource实际为SessionFactory,TransactionManager的实现为HibernateTransactionManager。
具体如下图:
根据代理机制的不同,总结了五种Spring事务的配置方式,配置文件如下:
第一种方式:每个Bean都有一个代理
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<bean
id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<propertyname="configLocation" value="classpath:hibernate.cfg.xml"/>
<propertyname="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration"/>
</bean>
<!-- 定义事务管理器(声明式的事务) -->
<bean
id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<propertyname="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- 配置DAO -->
<bean
id="userDaoTarget" class="com.bluesky.spring.dao.UserDaoImpl">
<propertyname="sessionFactory" ref="sessionFactory"/>
</bean>
<bean
id="userDao"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<!-- 配置事务管理器 -->
<propertyname="transactionManager" ref="transactionManager"/>
<propertyname="target" ref="userDaoTarget"/>
<propertyname="proxyInterfaces" value="com.bluesky.spring.dao.GeneratorDao"/>
<!-- 配置事务属性 -->
<propertyname="transactionAttributes">
<props>
<propkey="*">PROPAGATION_REQUIRED</prop>
定义一个用于创建对象(interface)的接口(这里的"接口"不是指interface而是method),
让子类(通过override父类创建interface的method来)决定实例化哪一个类,
Factory Method使一个类(interface)的实例化延迟到其(指Factory Method所在的类)子类。
@@@练习示例:
导出数据的应用框架。
@@@示例代码:
src/export/ExportFileApi.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package export; /** * 导出文件对象的接口 */ public interface ExportFileApi { /** * 导出内容成为文件 * @param data: 示意需要保存的数据 * @return 是否导出成功 */ public boolean export(String data); }
src/export/ExportTxtFile.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package export; /** * 导出成文本文件格式的对象 */ public class ExportTxtFile implements ExportFileApi { public boolean export(String data) { //简单示意一下,这里需要操作文件 System.out.println("导出数据" + data + "到文本文件"); return true; } }
src/export/ExportDB.java
~~~~~~~~~~~~~~~~~~~~~~~~
package export; /** * 导出成数据库备份文件形式的对象 */ public class ExportDB implements ExportFileApi { public boolean export(String data) { //简单示意一下,这里需要操作数据库和文件 System.out.println("导出数据" + data + "到数据库备份文件"); return true; } }
src/export/ExportOperate.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package export; /** * 实现导出数据的业务功能对象 */ public class ExportOperate { /** * 导出文件 * @param type 用户选择的导出类型 * @param data 需要保存的数据 * @return 是否成功导出文件 */ public boolean export(int type, String data) { //使用工厂方法 ExportFileApi api = factoryMethod(type); return api.export(data); } /** * 工厂方法,创建导出的文件对象的接口对象 * @param type 用户选择的导出类型 * @return 导出的文件对象的接口对象 */ protected ExportFileApi factoryMethod(int type) { ExportFileApi api = null; if (1 == type) { api = new ExportTxtFile(); } else if (2 == type) { api = new ExportDB(); } return api; } }
src/export/ExportTxtFileOperate.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package export; /** * 具体的创建器实现对象,实现创建导出成文本格式的对象 */ public class ExportTxtFileOperate extends ExportOperate { protected ExportFileApi factoryMethod() { //创建导出成文本格式的对象 return new ExportTxtFile(); } }
src/export/ExportDBOperate.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package export; /** * 具体的创建器实现对象,实现创建导出成数据库备份文件形式的对象 */ public class ExportDBOperate extends ExportOperate { protected ExportFileApi factoryMethod() { //创建导出成文本格式的对象 return new ExportDB(); } }
src/export/ExportXml.java
~~~~~~~~~~~~~~~~~~~~~~~~~
package export; /** * 导出成xml文件的对象 */ public class ExportXml implements ExportFileApi { public boolean export(String data) { // 简单示意一下 System.out.println("导出数据" + data + "到XML文件"); return true; } }
src/export/ExportOperate2.java
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package export; /** * 扩展ExportOperate对象,加入可以导出的XML文件 */ public class ExportOperate2 extends ExportOperate { /** * 覆盖父类的工厂方法,创建导出的文件对象的接口对象 * @param type 用户选择的导出类型 * @return 导出的文件对象的接口对象 */ protected ExportFileApi factoryMethod(int type) { ExportFileApi api = null; // 可以全部覆盖,也可以选择自己感兴趣的覆盖 // 这里只添加自己新的实现,其他的不管 if (3 == type) { api = new ExportXml(); } else { // 其他的还是让父类来实现 api = super.factoryMethod(type); } return api; } }
src/user/Client.java
~~~~~~~~~~~~~~~~~~~~
package user; import export.ExportOperate; import export.ExportOperate2; public class Client { public static void main(String[] args) { // 创建需要使用的Creator对象 ExportOperate operate = new ExportOperate2(); // 下面变换传入的参数来测试参数化工厂方法 operate.export(1, "Test1"); operate.export(2, "Test2"); operate.export(3, "Test3"); } }
@@@工厂方法模式的实现:
1. 一般实现成抽象类
2. 也可以实现成具体的类
3. 可以通过给工厂方法传递参数来选择实现
4. 工厂方法一般返回的是被创建对象的接口对象
5. 在工厂方法模式里面,是Creator中的其他方法在使用工厂方法创建的对象
6. 工厂方法一般不提供给外部使用(用protected修饰)
7. 可以使用工厂方法模式来连接平行的类层次
@@@工厂方法模式的优点 :
1. 可以在不知道所依赖的对象的具体实现的情况下编程
2. 更容易扩展对象的新版本
@@@工厂方法模式的缺点 :
1. 具体产品对象和工厂方法的耦合性
@@@工厂方法模式的本质:
延迟到子类来选择实现
@@@工厂方法模式体现的设计原则 :
依赖倒置原则
Atmosphere (http://atmosphere.dev.java.net) is a high-level API designed to make it easier to build Comet-based Web applications that include a mix of Comet and RESTful behavior. Today writing portable Web applications that can use the power of the Comet technique is almost impossible: Tomcat, Jetty, and Grizzly/GlassFish application server all have their own set of private APIs. Atmosphere offers API that will works everywhere without the needs to learn the web server specific API.
Atmosphere leverages and builds on Project Jersey and the Java API for RESTful Web Services (JAX-RS). Jersey is the open resource reference implementation of JAX-RS that makes it easier to build RESTful Web services. Atmosphere and Jersey complement each other, with the goal of making it easier to build Comet-based Web applications that include a mix of Comet and RESTful behavior.