3.3 模型层结构 Model层为整个系统的核心部分,完成应用的业务逻辑及与数据库的通信。AppFuse中将Model分为两层:持久层和业务层。采用Spring+Hibernate框架实现,这里以对用户User数据的操作为例详细阐述其实现方式。
对持久化数据的访问基于DAO(Data Access Object)模式实现。DAO模式提供了访问关系型数据库系统所需的所有接口操作的接口。DAO模式将底层数据访问操作与高层业务逻辑分离开,对上层提供面向对象的数据访问接口。
Model层与User相关的类有: POJO: User:管理员表的业务对象。 业务层: UserManager:业务层接口,为控制层所调用。 UserManagerImpl:业务层接口的实现,调用持久层接口。 持久层: UserDAO:持久层接口,为业务层实现所调用。 UserDAOHibernate:持久层接口的实现。 XML配置文件: applicationContext-service.xml:业务层接口的配置文件。 applicationContext-hibernate.xml:持久层接口的配置文件。
3.3.2 Spring的IoC Ioc(Inversion of Control)即反转控制。Ioc模式即Dependency Injection模式是依赖注射的意思,也就是将依赖先剥离,然后在适当时候再注射进入。 Spring的轻量级的bean容器为业务对象(business objects)、DAO对象和资源(如:JDBC数据源或者Hibernate SessionFactorie等)对象提供了IoC类型的装配能力。Spring使用一个xml格式的应用配置文件为开发者提供了一种通过解析定制的属性文件来手动管理单实例对象或者工厂对象的选择性。由于Spring将非入侵性做为一个重要的目标,因此可以由Spring配置管理的bean对象均不需要依赖Spring自有的接口和类就可以通过它们的bean属性完成配置。 就实现上来讲Spring采取了配置文件的形式来实现依赖的注射,并且支持Type2 IOC(Setter Injection)以及Type3 IOC(Constructor Injection)。 在Model层,使用Spring提供的Setter Injection(type2)注入方式。以User为例,下面是其用法。 在applicationContext- hibernate.xml中定义
在UserManager类中有一句: public void setUserDAO(UserDAO dao); 这就是一个DAO Object设置方法(注射器)。UserDAO将被调用,和持久层通信。以这种方式创建UserDAO的实例,同样达到了由UserManager创建UserDao的目的。避免了直接实例化UserDAO的实现而使业务层和持久层紧密耦合。
在控制层调用业务层方法时,使用服务定位器返回给Spring context,Spring的BeanFactory提供了getBean方法。BeanFactory是一个通用的Factory,它使对象能够按名称获取,并且能管理对象之间的关系。 在applicationContext-service.xml中配置
在控制层BaseAction定义通用方法:
在UserAction中创建UserManager的实例: UserManager mgr = (UserManager) getBean("userManager"); 这样,通过BeanFactory的getBean方法,以及xml配置文件,避免了在UserAction类中直接实例化UserManager,消除了控制层与业务层及业务层与持久层之间的耦合,实现了依赖的注射。 ApplicationContext 是BeanFactory的子接口,为下列东西提供支持: 信息查找,支持着国际化 事件机制,允许发布应用对象以及可选的注册以接收到事件 可移植的文件和资源访问
3.3.3 Spring的事务管理 在数据持久层的杰出贡献,可能是Spring最为闪亮的优点。 Spring提供了通过容器的集约式参数化事务机制,实现事务的外部管理。容器管理的参数化事务为程序开发提供了相当的灵活性,同时因为将事务委托给容器进行管理,应用逻辑中无需再编写事务代码,大大节省了代码量(特别是针对需要同时操作多个事务资源的应用),从而提高了生产率。 AppFuse在applicationContext-service.xml文件中进行了对事务的配置
这里定义了一个名为txProxyTemplate的TransactionProxyFactoryBean服务。它对包含实际数据逻辑的持久层对象进行了事务的封装。在这里,通过transactionAttributes属性,我们指定了事务的管理策略,即将所有的名称以save和remove开头的方法纳入事务管理范围。如果此方法中抛出异常,则Spring将当前事务回滚,如果方法正常结束,则提交事务。 而对所有其它方法则以只读的事务处理机制进行处理。设为只读型事务,可以使持久层尝试对数据操作进行优化,如对于只读事务Hibernate将不执行flush操作,而某些数据库连接池和JDBC 驱动也对只读型操作进行了特别优化。 如果有其他的方法需要进行写数据库操作,可以在相应的Manager配置中声明。如在UserManager中,就添加了属性
这样,以LoginCookie结尾的方法也可以写数据库了。 Spring可以将任意Java Class 纳入事务管理,而无需对其进行任何修改,因此我们的类可能完全不知道它正在被进行事务管理。
3.3.3 Spring+Hibernate操作持久层 Spring对Hibernate有很好的支持。 Hibernate中通过SessionFactory创建和维护Session。Spring对SessionFactory的配置进行了整合,无需再通过Hibernate.cfg.xml对SessionFactory进行设定。SessionFactory节点的mappingResources属性包含了映射文件的路径,list节点下可配置多个映射文件。hibernateProperties节点则容纳了所有的属性配置。可以对应传统的Hibernate.cfg.xml文件结构对这里的SessionFactory配置进行解读。 下面是HibernateSessionFactory 和 HibernateTransactionManager的配置: 在applicationContext-hibernate.xml中:
Spring 提供了一个 HibernateTransactionManager,采用面向Hibernate的TransactionManager实现:org.springframework.orm.hibernate.HibernateTransactionManager。他用线程捆绑了一个Hibernate Session,用它来支持transactions。
sessionFactory Bean引用了HibernateSessionFactory,而transactionManager Bean引用了HibernateTransactionManage。 transactionManager Bean中有个sessionFactory属性。 HibernateTransactionManager有个sessionFactory setter 和 getter方法,用来在Spring启动的时候实现“依赖注入” (dependency injection)的。 在sessionFactory 属性里引用sessionFactory Bean。这两个对象在Spring容器初始化后就被组装了起来了。 User使用一个TransactionProxyFactoryBean,它定义了一个setTransactionManager()。能很方便的处理申明的事物还有Service Object。TransactionProxyFactoryBean 还有个setter. 这会被Business service object(UserManager)引用, UserManager定义了业务层,并且它还有个属性,由setUserDAO()引用。
系统持久层中所有的类都继承自Spring提供的HibernateDaoSupport类,HibernateSupport实现了HibernateTemplate和SessionFactory实例的关联。HibernateTemplate对Hibernate Session操作进行了封装,提供了一个简单的方式实现了Hibernate-based DAO对象。借助HibernateTemplate我们可以脱离每次数据操作必须首先获得Session实例、启动事务、提交/回滚事务以及烦杂的try/catch/finally的繁琐操作。一个简单的Hibernate访问方法就完全解决了些麻烦! 无论是在多个DAO接口还是在多方事务的情况下,Spring使得多种DAO对象无缝地协同工作。 对于简单的单步的动作,象find, load, saveOrUpdate或者delete的调用,HibernateTemplate提供更为便利的选择以代替象一行的回调的执行。此外HibernateDaoSupport类提供了setSessionFactory方法来接受一个SessionFactory,同时提供了getSessionFactory和getHibernateTemplate方法供其继承类使用。将这些结合起来,允许对于典型的需求给出了非常简单的DAO实现,如获得所有用户的方法:
Powered by: BlogJava Copyright © kook