AppFuse学习笔记-模型层

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中定义
    <bean id="userDAO" class="org.appfuse.dao.hibernate.UserDAOHibernate">
        <property name="sessionFactory"><ref local="sessionFactory"/></property>
    </bean>
    在UserManager类中有一句:
    public void setUserDAO(UserDAO dao);
    这就是一个DAO Object设置方法(注射器)。UserDAO将被调用,和持久层通信。以这种方式创建UserDAO的实例,同样达到了由UserManager创建UserDao的目的。避免了直接实例化UserDAO的实现而使业务层和持久层紧密耦合。
 

    在控制层调用业务层方法时,使用服务定位器返回给Spring context,Spring的BeanFactory提供了getBean方法。BeanFactory是一个通用的Factory,它使对象能够按名称获取,并且能管理对象之间的关系。
    在applicationContext-service.xml中配置
    <bean id="userManager" parent="txProxyTemplate">
        <property name="target">
            <bean class="org.appfuse.service.impl.UserManagerImpl">
                <property name="userDAO"><ref bean="userDAO"/></property>
            </bean>
        </property>
    </bean>
    在控制层BaseAction定义通用方法:
    private static ApplicationContext ctx = null;
    public Object getBean(String name) {
        if (ctx == null) {
            ctx = WebApplicationContextUtils
                    .getRequiredWebApplicationContext(servlet.getServletContext());
        }
        return ctx.getBean(name);
    }
    在UserAction中创建UserManager的实例:
        UserManager mgr = (UserManager) getBean("userManager");
    这样,通过BeanFactory的getBean方法,以及xml配置文件,避免了在UserAction类中直接实例化UserManager,消除了控制层与业务层及业务层与持久层之间的耦合,实现了依赖的注射。
    ApplicationContext 是BeanFactory的子接口,为下列东西提供支持:
        信息查找,支持着国际化
        事件机制,允许发布应用对象以及可选的注册以接收到事件
        可移植的文件和资源访问

3.3.3 Spring的事务管理
    在数据持久层的杰出贡献,可能是Spring最为闪亮的优点。
    Spring提供了通过容器的集约式参数化事务机制,实现事务的外部管理。容器管理的参数化事务为程序开发提供了相当的灵活性,同时因为将事务委托给容器 进行管理,应用逻辑中无需再编写事务代码,大大节省了代码量(特别是针对需要同时操作多个事务资源的应用),从而提高了生产率。
    AppFuse在applicationContext-service.xml文件中进行了对事务的配置
    <bean id="txProxyTemplate" abstract="true"
        class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        <property name="transactionManager"><ref bean="transactionManager"/></property>
        <property name="transactionAttributes">
            <props>
                <prop key="save*">PROPAGATION_REQUIRED</prop>
                <prop key="remove*">PROPAGATION_REQUIRED</prop>
                <prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
            </props>
        </property>
    </bean>
    这里定义了一个名为txProxyTemplate的TransactionProxyFactoryBean服务。它对包含实际数据逻辑的持久层对象进 行了事务的封装。在这里,通过transactionAttributes属性,我们指定了事务的管理策略,即将所有的名称以save和remove开头 的方法纳入事务管理范围。如果此方法中抛出异常,则Spring将当前事务回滚,如果方法正常结束,则提交事务。
    而对所有其它方法则以只读的事务处理机制进行处理。设为只读型事务,可以使持久层尝试对数据操作进行优化,如对于只读事务Hibernate将不执行flush操作,而某些数据库连接池和JDBC 驱动也对只读型操作进行了特别优化。
    如果有其他的方法需要进行写数据库操作,可以在相应的Manager配置中声明。如在UserManager中,就添加了属性
        <property name="transactionAttributes">
            <props>
                <prop key="save*">PROPAGATION_REQUIRED</prop>
                <prop key="remove*">PROPAGATION_REQUIRED</prop>
                <prop key="*LoginCookie">PROPAGATION_REQUIRED</prop>
                <prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
            </props>
        </property>
    这样,以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中:
    <bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
        <property name="dataSource"><ref bean="dataSource"/></property>
        <property name="mappingResources">
            <list>
                <value>com/mycompany/model/User.hbm.xml</value>
                ……………………………
            </list>
        </property>

        <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">@HIBERNATE-DIALECT@</prop>
            <!--prop key="hibernate.show_sql">true</prop-->
            <!--prop key="hibernate.hbm2ddl.auto">update</prop-->
        </props>
        </property>
    </bean>

    Spring 提供了一个 HibernateTransactionManager,采用面向Hibernate的TransactionManager实现: org.springframework.orm.hibernate.HibernateTransactionManager。他用线程捆绑了一个 Hibernate Session,用它来支持transactions。
    <bean id="transactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager">
        <property name="sessionFactory"><ref local="sessionFactory"/></property>
    </bean>

    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实现,如获得所有用户的方法:
    public List getUsers(User user) {
        return getHibernateTemplate().find("from User u order by upper(u.username)");
    }


posted on 2007-06-18 18:09 chenguo 阅读(144) 评论(0)  编辑  收藏 所属分类: J2ee Dev


只有注册用户登录后才能发表评论。


网站导航:
 
<2024年12月>
24252627282930
1234567
891011121314
15161718192021
22232425262728
2930311234

导航

统计

留言簿

随笔分类(1)

文章分类(52)

好友 小山的博客

最新随笔

最新评论