AppFuse學習筆記-模型層

          3.3 模型層結(jié)構(gòu)
              Model層為整個系統(tǒng)的核心部分,完成應用的業(yè)務(wù)邏輯及與數(shù)據(jù)庫的通信。AppFuse中將Model分為兩層:持久層和業(yè)務(wù)層。采用Spring+Hibernate框架實現(xiàn),這里以對用戶User數(shù)據(jù)的操作為例詳細闡述其實現(xiàn)方式。

              對持久化數(shù)據(jù)的訪問基于DAO(Data Access Object)模式實現(xiàn)。DAO模式提供了訪問關(guān)系型數(shù)據(jù)庫系統(tǒng)所需的所有接口操作的接口。DAO模式將底層數(shù)據(jù)訪問操作與高層業(yè)務(wù)邏輯分離開,對上層提供面向?qū)ο蟮臄?shù)據(jù)訪問接口。

              Model層與User相關(guān)的類有:
              POJO:
              User:管理員表的業(yè)務(wù)對象。
              業(yè)務(wù)層:
              UserManager:業(yè)務(wù)層接口,為控制層所調(diào)用。
              UserManagerImpl:業(yè)務(wù)層接口的實現(xiàn),調(diào)用持久層接口。
              持久層:
              UserDAO:持久層接口,為業(yè)務(wù)層實現(xiàn)所調(diào)用。
              UserDAOHibernate:持久層接口的實現(xiàn)。
              XML配置文件:
              applicationContext-service.xml:業(yè)務(wù)層接口的配置文件。
              applicationContext-hibernate.xml:持久層接口的配置文件。

          3.3.2 Spring的IoC
              Ioc(Inversion of Control)即反轉(zhuǎn)控制。Ioc模式即Dependency Injection模式是依賴注射的意思,也就是將依賴先剝離,然后在適當時候再注射進入。
              Spring的輕量級的bean容器為業(yè)務(wù)對象(business objects)、DAO對象和資源(如:JDBC數(shù)據(jù)源或者Hibernate SessionFactorie等)對象提供了IoC類型的裝配能力。Spring使用一個xml格式的應用配置文件為開發(fā)者提供了一種通過解析定制的屬 性文件來手動管理單實例對象或者工廠對象的選擇性。由于Spring將非入侵性做為一個重要的目標,因此可以由Spring配置管理的bean對象均不需 要依賴Spring自有的接口和類就可以通過它們的bean屬性完成配置。
              就實現(xiàn)上來講Spring采取了配置文件的形式來實現(xiàn)依賴的注射,并且支持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設(shè)置方法(注射器)。UserDAO將被調(diào)用,和持久層通信。以這種方式創(chuàng)建UserDAO的實例,同樣達到了由UserManager創(chuàng)建UserDao的目的。避免了直接實例化UserDAO的實現(xiàn)而使業(yè)務(wù)層和持久層緊密耦合。
           

              在控制層調(diào)用業(yè)務(wù)層方法時,使用服務(wù)定位器返回給Spring context,Spring的BeanFactory提供了getBean方法。BeanFactory是一個通用的Factory,它使對象能夠按名稱獲取,并且能管理對象之間的關(guān)系。
              在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中創(chuàng)建UserManager的實例:
                  UserManager mgr = (UserManager) getBean("userManager");
              這樣,通過BeanFactory的getBean方法,以及xml配置文件,避免了在UserAction類中直接實例化UserManager,消除了控制層與業(yè)務(wù)層及業(yè)務(wù)層與持久層之間的耦合,實現(xiàn)了依賴的注射。
              ApplicationContext 是BeanFactory的子接口,為下列東西提供支持:
                  信息查找,支持著國際化
                  事件機制,允許發(fā)布應用對象以及可選的注冊以接收到事件
                  可移植的文件和資源訪問

          3.3.3 Spring的事務(wù)管理
              在數(shù)據(jù)持久層的杰出貢獻,可能是Spring最為閃亮的優(yōu)點。
              Spring提供了通過容器的集約式參數(shù)化事務(wù)機制,實現(xiàn)事務(wù)的外部管理。容器管理的參數(shù)化事務(wù)為程序開發(fā)提供了相當?shù)撵`活性,同時因為將事務(wù)委托給容器 進行管理,應用邏輯中無需再編寫事務(wù)代碼,大大節(jié)省了代碼量(特別是針對需要同時操作多個事務(wù)資源的應用),從而提高了生產(chǎn)率。
              AppFuse在applicationContext-service.xml文件中進行了對事務(wù)的配置
              <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服務(wù)。它對包含實際數(shù)據(jù)邏輯的持久層對象進 行了事務(wù)的封裝。在這里,通過transactionAttributes屬性,我們指定了事務(wù)的管理策略,即將所有的名稱以save和remove開頭 的方法納入事務(wù)管理范圍。如果此方法中拋出異常,則Spring將當前事務(wù)回滾,如果方法正常結(jié)束,則提交事務(wù)。
              而對所有其它方法則以只讀的事務(wù)處理機制進行處理。設(shè)為只讀型事務(wù),可以使持久層嘗試對數(shù)據(jù)操作進行優(yōu)化,如對于只讀事務(wù)Hibernate將不執(zhí)行flush操作,而某些數(shù)據(jù)庫連接池和JDBC 驅(qū)動也對只讀型操作進行了特別優(yōu)化。
              如果有其他的方法需要進行寫數(shù)據(jù)庫操作,可以在相應的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結(jié)尾的方法也可以寫數(shù)據(jù)庫了。
              Spring可以將任意Java Class 納入事務(wù)管理,而無需對其進行任何修改,因此我們的類可能完全不知道它正在被進行事務(wù)管理。


          3.3.3 Spring+Hibernate操作持久層
              Spring對Hibernate有很好的支持。
              Hibernate中通過SessionFactory創(chuàng)建和維護Session。Spring對SessionFactory的配置進行了整合,無需再 通過Hibernate.cfg.xml對SessionFactory進行設(shè)定。SessionFactory節(jié)點的mappingResources 屬性包含了映射文件的路徑,list節(jié)點下可配置多個映射文件。hibernateProperties節(jié)點則容納了所有的屬性配置??梢詫獋鹘y(tǒng)的 Hibernate.cfg.xml文件結(jié)構(gòu)對這里的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實現(xiàn): 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啟動的時候?qū)崿F(xiàn)“依賴注入” (dependency injection)的。 在sessionFactory 屬性里引用sessionFactory Bean。這兩個對象在Spring容器初始化后就被組裝了起來了。
           
              User使用一個TransactionProxyFactoryBean,它定義了一個setTransactionManager()。能很方便的處 理申明的事物還有Service Object。TransactionProxyFactoryBean 還有個setter. 這會被Business service object(UserManager)引用, UserManager定義了業(yè)務(wù)層,并且它還有個屬性,由setUserDAO()引用。

              系統(tǒng)持久層中所有的類都繼承自Spring提供的HibernateDaoSupport類,HibernateSupport實現(xiàn)了 HibernateTemplate和SessionFactory實例的關(guān)聯(lián)。HibernateTemplate對Hibernate Session操作進行了封裝,提供了一個簡單的方式實現(xiàn)了Hibernate-based DAO對象。借助HibernateTemplate我們可以脫離每次數(shù)據(jù)操作必須首先獲得Session實例、啟動事務(wù)、提交/回滾事務(wù)以及煩雜的 try/catch/finally的繁瑣操作。一個簡單的Hibernate訪問方法就完全解決了些麻煩! 無論是在多個DAO接口還是在多方事務(wù)的情況下,Spring使得多種DAO對象無縫地協(xié)同工作。
              對于簡單的單步的動作,象find, load, saveOrUpdate或者delete的調(diào)用,HibernateTemplate提供更為便利的選擇以代替象一行的回調(diào)的執(zhí)行。此外 HibernateDaoSupport類提供了setSessionFactory方法來接受一個SessionFactory,同時提供了 getSessionFactory和getHibernateTemplate方法供其繼承類使用。將這些結(jié)合起來,允許對于典型的需求給出了非常簡單 的DAO實現(xiàn),如獲得所有用戶的方法:
              public List getUsers(User user) {
                  return getHibernateTemplate().find("from User u order by upper(u.username)");
              }


          posted on 2007-06-18 18:09 chenguo 閱讀(157) 評論(0)  編輯  收藏 所屬分類: J2ee Dev

          <2025年7月>
          293012345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          導航

          統(tǒng)計

          留言簿

          隨筆分類(1)

          文章分類(52)

          好友 小山的博客

          最新隨筆

          最新評論

          主站蜘蛛池模板: 江城| 和田县| 文水县| 六安市| 阜阳市| 灵台县| 乌拉特前旗| 易门县| 汪清县| 怀化市| 开阳县| 中宁县| 裕民县| 太谷县| 麻阳| 石河子市| 南木林县| 谢通门县| 华阴市| 那坡县| 东阳市| 常州市| 商洛市| 湖南省| 平舆县| 和静县| 尉氏县| 米林县| 霍州市| 广东省| 庆阳市| 靖宇县| 庆云县| 盈江县| 镇沅| 靖江市| 鄱阳县| 梓潼县| 宜兴市| 平阳县| 本溪市|