海鷗航際

          JAVA站
          posts - 11, comments - 53, trackbacks - 1, articles - 102

          Spring Framework之最佳實(shí)踐

          Posted on 2005-01-12 20:45 海天一鷗 閱讀(732) 評(píng)論(0)  編輯  收藏 所屬分類: J2EE

           

           

          Spring Framework從誕生之日起,受到了越來(lái)越多的關(guān)注。最近,新的開(kāi)源項(xiàng)目大多支持Spring Framework。國(guó)內(nèi)目前也有專門的網(wǎng)站(http://spring.jactiongroup.net/)。那它為什么如此受歡迎呢?

          我想最重要的是,EJB讓每個(gè)人都痛恨。要編寫一個(gè)EJB,需要寫LocalHome, RemoteHome, Bean, LocalInterface, RemoteInterface,需要一個(gè)標(biāo)準(zhǔn)描述符,一個(gè)特殊廠商描述符(Weblogic、WebSphere都不一樣),如果是Entity Bean,還需要Mapping文件。如此之多,實(shí)在麻煩。但EJB最重要的是解決Transaction問(wèn)題,沒(méi)有Spring之前,沒(méi)有其他方法能夠描述式的解決它。每個(gè)人、每個(gè)公司為了解決Transaction的問(wèn)題,編程的寫法都不一樣,百花齊放。于是,在最需要它的時(shí)候,Spring出現(xiàn)了。

          Spring的功能非常多。但對(duì)于一個(gè)產(chǎn)品,最重要的是如何用好它的精華。Spring包含AOP、ORM、DAO、Context、Web、MVC幾個(gè)部分組成。Web、MVC暫不用考慮,用成熟的Struts、JSP或Webwork更好。DAO由于目前Hibernate、JDO的流行,也可不考慮。因此最需要用的是AOP、ORM、Context。

          Context中,最重要的是Beanfactory,它是將接口與實(shí)現(xiàn)分開(kāi),非常重要。以前我們寫程序,如一個(gè)接口IDocument,一個(gè)實(shí)現(xiàn)類Document1。在寫程序時(shí),需寫成IDocument doc = new Document1(),一旦我們的實(shí)現(xiàn)類需改變時(shí),變?yōu)镈ocument2,則程序需寫成IDocument doc = new Document2(),所有用到的地方全需改。Beanfactory幫我們解決了這個(gè)問(wèn)題,用context后,寫法變?yōu)镮Document doc=(IDocument)beanFactory.getBean("doc")。如果實(shí)現(xiàn)類從Document1改為Document2,直接在配置文件改就可以了。Context是Bean factory的進(jìn)一步抽象。很多人都喜歡用ApplicationConext,用Servlet把它Load。這樣就把Bean Factory與Web綁定在一起。如果是Fat Client或Remote調(diào)用,則這些Bean factory就很難調(diào)用,實(shí)際是將表現(xiàn)層與業(yè)務(wù)層綁定的太緊。推薦的方法是SingletonBeanFactoryLocator。具體為:

             BeanFactoryLocator bfLocator = SingletonBeanFactoryLocator.getInstance();
             BeanFactoryReference bf = bfLocator.useBeanFactory("beanFactory");
             // now use some bean from factory
             return bf.getFactory().getBean(name);

           

           <beans>

               <bean id="beanFactory" class="org.springframework.context.support.ClassPathXmlApplicationContext">
               <constructor-arg>
                <list>
                 <value>dataAccessContext.xml</value>
                 <value>securityContext.xml</value>
                 <value>...</value>
                </list>
               </constructor-arg>
              </bean>

          </beans>


          這樣,就可隨時(shí)動(dòng)態(tài)擴(kuò)展,實(shí)現(xiàn)組件式的開(kāi)發(fā)。

          Spring Framework最得以出名的是與Hibernate的無(wú)縫鏈接,基本上用Spring,就會(huì)用Hibernate。可惜的是Spring提供的HibernateTemplate功能顯得不夠,使用起來(lái)也不是很方便。我們編程序時(shí),一般先寫B(tài)usinessService,由BusinessService調(diào)DAO來(lái)執(zhí)行存儲(chǔ),在這方面Spring沒(méi)有很好的例子,造成真正想用好它,并不容易。

          我們的思路是先寫一個(gè)BaseDao,仿照HibernateTemplate,將基本功能全部實(shí)現(xiàn):

          public class BaseDao extends HibernateDaoSupport{

              private Log log = LogFactory.getLog(getClass());

              public Session openSession() {
                  return SessionFactoryUtils.getSession(getSessionFactory(), false);
              }

              public Object get(Class entityClass, Serializable id) throws DataAccessException {
                  Session session = openSession();
                  try {
                      return session.get(entityClass, id);
                  }
                  catch (HibernateException ex) {
                      throw SessionFactoryUtils.convertHibernateAccessException(ex);
                  }
              }

              public Serializable create(Object entity) throws DataAccessException {
                  Session session = openSession();
                  try {
                      return session.save(entity);
                  }
                  catch (HibernateException ex) {
                      throw SessionFactoryUtils.convertHibernateAccessException(ex);
                  }
              }

          ...

          其它的DAO,從BaseDao繼承出來(lái),這樣寫其他的DAO,代碼就會(huì)很少。

          從BaseDao繼承出來(lái)EntityDao,專門負(fù)責(zé)一般實(shí)體的基本操作,會(huì)更方便。

          public interface EntityDao {

              public Object get(Class entityClass, Serializable id) throws DataAccessException;

              public Object load(Class entityClass, Serializable id) throws DataAccessException;

              public Serializable create(Object entity) throws DataAccessException;
          ...}

          /**
           * Base class for Hibernate DAOs.  This class defines common CRUD methods for
           * child classes to inherit. User Sping AOP Inteceptor
           */
          public class EntityDaoImpl extends BaseDao implements EntityDao{

          }

          為了Transaction的控制,采用AOP的方式:

          public interface EntityManager {

              public Object get(Class entityClass, Serializable id);

              public Object load(Class entityClass, Serializable id);

              public Serializable create(Object entity);
          ...

          }

          /**
           * Base class for Entity Service. User Sping AOP Inteceptor
           */
          public class EntityManagerImpl implements EntityManager {

              private EntityDao entityDao;

              public void setEntityDao(EntityDao entityDao) {
                  this.entityDao = entityDao;
              }

              public Object get(Class entityClass, Serializable id) {
                  return entityDao.get(entityClass, id);
              }

              public Object load(Class entityClass, Serializable id) {
                  return entityDao.load(entityClass, id);
              }
          ...

          }

          這樣我們就有了一個(gè)通用的Hibernate實(shí)體引擎,可以對(duì)任何Hibernate實(shí)體實(shí)現(xiàn)基本的增加、修改、刪除、查詢等。

          其它的BusinessService就可以繼承EntityManager,快速實(shí)現(xiàn)業(yè)務(wù)邏輯。

          具體XML配置如下:

           <!-- Oracle JNDI DataSource for J2EE environments -->
           <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
            <property name="jndiName"><value>java:comp/env/jdbc/testPool</value></property>
           </bean>

           <!-- Hibernate SessionFactory for Oracle -->
           <!-- Choose the dialect that matches your "dataSource" definition -->
           <bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
            <property name="dataSource"><ref local="dataSource"/></property>
            <property name="mappingResources">
             <value>user-hbm.xml</value>
            </property>
            <property name="hibernateProperties">
             <props>
              <prop key="hibernate.dialect">net.sf.hibernate.dialect.OracleDialect</prop>
              <prop key="hibernate.cache.provider_class">net.sf.ehcache.hibernate.Provider</prop>
              <prop key="hibernate.cache.use_query_cache">true</prop>
                            <prop key="hibernate.show_sql">false</prop>
             </props>
            </property>
           </bean>

           <!-- AOP DAO Intecepter -->
                  <bean id="hibernateInterceptor" class="org.springframework.orm.hibernate.HibernateInterceptor">
                    <property name="sessionFactory">
                      <ref bean="sessionFactory"/>
                    </property>
                  </bean>

                  <bean id="entityDaoTarget" class="com.gpower.services.entity.dao.EntityDaoImpl">
                    <property name="sessionFactory">
                      <ref bean="sessionFactory"/>
                    </property>
                  </bean>

                  <bean id="entityDao" class="org.springframework.aop.framework.ProxyFactoryBean">
                    <property name="proxyInterfaces">
                      <value>com.gpower.services.entity.dao.EntityDao</value>
                    </property>
                    <property name="interceptorNames">
                      <list>
                        <value>hibernateInterceptor</value>
                        <value>entityDaoTarget</value>
                      </list>
                    </property>
                  </bean>

           <!-- Transaction manager for a single Hibernate SessionFactory (alternative to JTA) -->
           <bean id="transactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager">
            <property name="sessionFactory"><ref local="sessionFactory"/></property>
           </bean>

           <!-- Transaction manager that delegates to JTA (for a transactional JNDI DataSource) -->
           <!--
           <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>
           -->

           <!-- Transactional proxy for the Application primary business object -->
                  <bean id="entityManagerTarget" class="com.gpower.services.entity.EntityManagerImpl">
                    <property name="entityDao">
                      <ref bean="entityDao"/>
                    </property>
                  </bean>

                  <bean id="entityManager" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
                    <property name="transactionManager">
                      <ref bean="transactionManager"/>
                    </property>
                    <property name="target">
                      <ref bean="entityManagerTarget"/>
                    </property>
                    <property name="transactionAttributes">
               <props>
                 <prop key="get*">PROPAGATION_SUPPORTS</prop>
                 <prop key="*">PROPAGATION_REQUIRED</prop>
               </props>
                    </property>
                  </bean>

          資源:Spring+Hibernate培訓(xùn)ppt

           

           

           

           

          主站蜘蛛池模板: 定陶县| 阿鲁科尔沁旗| 南部县| 修水县| 犍为县| 延津县| 涟源市| 容城县| 陕西省| 平顶山市| 民和| 新化县| 嘉祥县| 临沧市| 玉山县| 永嘉县| 荣昌县| 宁强县| 徐州市| 浦县| 崇义县| 和龙市| 冕宁县| 景宁| 防城港市| 北安市| 永丰县| 左云县| 宝坻区| 东台市| 阳江市| 于田县| 怀来县| 娱乐| 遵义县| 大同县| 鄯善县| 科技| 岢岚县| 双流县| 石城县|