posts - 310, comments - 6939, trackbacks - 0, articles - 3
            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          Spring VS EJB 3 的若干認(rèn)識誤區(qū)

          Posted on 2008-01-30 12:54 詩特林 閱讀(5837) 評論(8)  編輯  收藏 所屬分類: Spring
           應(yīng)IT168寫的專稿:http://publish.itpub.net/j/2008-01-29/200801291007089.shtml
           

          Spring VS EJB 3 的若干認(rèn)識誤區(qū)

           

          在開源領(lǐng)域,Spring開源框架已成為企業(yè)應(yīng)用開發(fā)中使用最多的開源框架。Spring框架的優(yōu)秀不但表現(xiàn)在其優(yōu)雅的底層設(shè)計(jì)、使用方便快捷、面向工作實(shí)踐、超強(qiáng)粘合能力等方面,另外一個(gè)不可忽視的方面是Spring擁有一個(gè)世界一流且活躍的技術(shù)開發(fā)團(tuán)隊(duì)。隨著Spring的流行,于是,大家開始對比Spring與另一種流行的框架組件EJB。目前網(wǎng)上關(guān)于SpringEJB的爭論頗多。很多架構(gòu)師認(rèn)為Spring會替代EJB,也有架構(gòu)師認(rèn)為Spring是開源的東西,是不成熟且無法和商業(yè)解決方案媲美的框架,因此,在SpringEJB的對比過程,有若干對Spring的片面認(rèn)識。而本文希望通過對這些誤區(qū)的分析,給Spring一個(gè)原本的認(rèn)識與理解。

          一、        前言

          EJB 3.0框架是JCP定義的并且被所有主流J2EE提供商支持的標(biāo)準(zhǔn)框架。EJB 3.0規(guī)范的發(fā)布版本目前已經(jīng)有開源的和商業(yè)的實(shí)現(xiàn),如JBOSSORACLEEJB 3.0大量使用了JAVA注解(Java annotations,是JDK1.5提供的新功能)。

          EJB最初的設(shè)計(jì)思想考慮的是為分布式的應(yīng)用服務(wù)的,分布式是針對大型應(yīng)用構(gòu)造的跨平臺的協(xié)作計(jì)算,EJB最初的目的就是為這種計(jì)算服務(wù)的。但是軟件發(fā)展到目前為止,大多數(shù)應(yīng)用不需要采用分布式的解決方案,因此用EJB顯得太臃腫了。Spring的出現(xiàn)恰恰為了解決這個(gè)問題。舉個(gè)例子來說,EJB就是導(dǎo)彈,專門設(shè)計(jì)為打高空飛機(jī)。但是現(xiàn)在發(fā)現(xiàn)飛機(jī)不多。于是將它用來對付步兵,這個(gè)實(shí)在太糟糕了。這個(gè)時(shí)候有人發(fā)明了狙擊步槍(Spring),發(fā)現(xiàn)對付步兵太好用了。

          Spring框架是一個(gè)廣受歡迎的但是非標(biāo)準(zhǔn)的開源框架。它主要由Interface21公司開發(fā)和控制。Spring框架的體系結(jié)構(gòu)是基于注射依賴(DI)模式。Spring框架使用了大量的XML配置文件,它可以獨(dú)立應(yīng)用,或者在現(xiàn)有的應(yīng)用服務(wù)器上工作。

          這兩個(gè)框架有著一個(gè)共同的核心設(shè)計(jì)理念:它們的目標(biāo)是為松耦合的POJO類提供中間件服務(wù)。框架通過在運(yùn)行時(shí)截取執(zhí)行環(huán)境,或?qū)⒎?wù)對象注射給POJO類的方式,將應(yīng)用服務(wù)和POJO連接起來。POJO類本身并不關(guān)注如何連接,而且也很少依賴于框架。

          這樣,開發(fā)者可以將注意力集中在業(yè)務(wù)邏輯上,可以對他們的POJO類進(jìn)行與框架無關(guān)的單元測試。并且,由于POJO類不需要繼承框架的類或?qū)崿F(xiàn)框架提供的接口,開發(fā)者可以在更加靈活性的基礎(chǔ)上構(gòu)建繼承體系,和搭建應(yīng)用。

          盡管有著共同的理念,但這兩個(gè)框架采取了不同的方式來提供POJO服務(wù)。由于已經(jīng)出了大量的比較SpringEJB3.0的文章。但發(fā)現(xiàn),隨著Spring的發(fā)展,其中對Spring的認(rèn)識難免有失偏頗的地方,因此,本文將考察它們之間幾個(gè)關(guān)鍵的認(rèn)識上的誤區(qū)進(jìn)行分析。

          二、        SpringXML VS EJB的注釋

          從應(yīng)用開發(fā)者的角度來看,Spring的編程接口主要基于XML配置文件,而EJB 3.0則大量的使用了JAVA注解。XML文件可以表達(dá)復(fù)雜的關(guān)系,但是它們更加冗長而且不健壯。注解的方式很簡單明了,但是很難去表達(dá)復(fù)雜的或者繼承性的結(jié)構(gòu)。

          由于EJB 3.0Spring相互學(xué)習(xí)了很多特性,所以,它們都在某種層次上支持XML和注釋。例如,EJB 3.0中可以應(yīng)用XML配置文件作為一個(gè)選擇性的機(jī)制,用來改變注釋的默認(rèn)行為。注釋也可以用來配置一些Spring服務(wù)。

          Spring 2中,采用了@PersistenceContext注釋的方式來整合JPAJava 持久性 API),從而實(shí)現(xiàn)了EntityManager對象的注入,同時(shí)通過@Transactional實(shí)現(xiàn)聲明式事務(wù)管理。Spring 2利用注釋來支持AspectJ(一種面向切面的框架,它擴(kuò)展了Java語言),如@Aspect@Before@After@Around等等注釋。Spring 2中,使用@Repository注釋,可以直接操作JPAHibernate API,而不需要使用Spring模板。

          Spring的元數(shù)據(jù)模型非常的靈活的,因此在Spring中可以快速的建立起基于注釋的元數(shù)據(jù)模型。而從最近發(fā)布的Spring 2.5看來,事實(shí)上也是這樣。Spring 2.5全面支持JSR-250注釋(JSR-250技術(shù)規(guī)范主要涉及J2SEJ2EE平臺上開發(fā)普通語義概念的標(biāo)注,提供一種獨(dú)立技術(shù)),如@Resource@PostConstruct@PreDestroy@WebServiceRef@EJB

          特別值得一提的是@Resource,最早是為了在EJB 3使用Spring的依賴注入功能。但如今其功能已經(jīng)擴(kuò)展了,不但支持像JNDI的查找,還可以注入任何的Spring管理對象。這就把Spring的優(yōu)勢(Spring支持任何對象的依賴注入)和EJB的優(yōu)勢(使用注釋代替XML)充分的結(jié)合起來了。

          Spring 2.5中提供了完整的基于注釋的依賴注入模型,如@Autowired@Qualifier注釋。用戶通過@Autowired注解來對Bean的屬性變量、屬性Setter方法以及構(gòu)造函數(shù)進(jìn)行標(biāo)注,配合AutowiredAnnotationBeanPostProcessor完成對Bean的自動裝配。

          @Component注釋為用戶自定義原形進(jìn)行了擴(kuò)展。Spring可以自動的檢測到注釋的組件。例如下面的代碼

          <context:component-scan base-package="org.springframework.samples.petclinic.web" />

          Web控制器不需要額外的XML配置,因?yàn)槭褂昧嘶谧⑨尩囊蕾囎⑷胍约盎谧⑨尩恼埱笥成洹?/span>Web控制器通過如下的代碼進(jìn)行管理:

          @Controller
          public class ClinicController {

             private final Clinic clinic;

             @Autowired
             public ClinicController(Clinic clinic) {
                this.clinic = clinic;
             }

          三、        EJB使用JPASpring使用Hibernate

          很多人都認(rèn)為,在EJB 3中通過使用@PersistenceContext注釋提供的entityManager對象來獲得JPA的數(shù)據(jù)訪問,而在Spring中,通過對SessionFactory對象的注入獲得Hibernate數(shù)據(jù)訪問。從而自然而然地認(rèn)中,EJB使用JPA來操作數(shù)據(jù)對象,而Spring使用Hibernate來操作數(shù)據(jù)對象。

          作為EJB3.0的一部分,JPA是一個(gè)好東西。其簡單的配置方式及強(qiáng)大的默認(rèn)配置支持,使其可以輕松自由的存在于輕量與重量之間。事實(shí)上,Spring同樣支持使用JPA來操作數(shù)據(jù)對象(例如JpaTemplate),此外Spring提供了@PersistenceContext注釋來支持JPA。在輕量級 Spring 框架的第二代中添加了一大批特性,即使是新的服務(wù)器應(yīng)用程序開發(fā)人員也能夠輕松上手。其關(guān)鍵增強(qiáng)之一就是 Spring 2 JPA的集成。@PersistenceContext注釋的使用示例如下面的代碼所示:

          package quickstart.service;

          import java.util.List;

          import javax.persistence.EntityManager;
          import javax.persistence.PersistenceContext;
          import javax.persistence.Query;

          import org.springframework.transaction.annotation.Transactional;

          import quickstart.model.Person;

          @Transactional
          public class PersonServiceImpl implements PersonService {
              private EntityManager em;

              @PersistenceContext
              public void setEntityManager(EntityManager em) {
                  this.em = em;
              }

              @SuppressWarnings("unchecked")
              public List<Person> findAll() {
                  Query query = getEntityManager().createQuery("select p FROM Person p");
                  return query.getResultList();
              }

              public void save(Person person) {
                  if (person.getId() == null) {
                      // new
                      em.persist(person);
                  } else {
                      // update
                      em.merge(person);
                  }
              }

              public void remove(int id) {
                  Person person = find(id);
                  if (person != null) {
                      em.remove(person);
                  }
              }

              private EntityManager getEntityManager() {
                  return em;
              }

              public Person find(int id) {
                  return em.find(Person.class
           id);
              }

          }

          @PersistenceContext會讓Spring在實(shí)例化的時(shí)候給服務(wù)注入一個(gè)EntityManager@PersistenceContext注解可以放在實(shí)例變量,或者setter方法前面。如果一個(gè)類被注解為@TransactionalSpring將會確保類的方法在運(yùn)行在一個(gè)事務(wù)中。

          當(dāng) Spring JPA 應(yīng)用程序在 Tomcat 上運(yùn)行時(shí),要讓 JPA 支持正常工作,需要在類裝入期間進(jìn)行字節(jié)碼連接。來自 Tomcat 的標(biāo)準(zhǔn)類裝入器不支持這個(gè),需要用特定于 Spring 的類裝入器實(shí)現(xiàn)這個(gè)功能。要把這個(gè)特定于 Spring 的類裝入器安裝到 Tomcat 服務(wù)器,首先要把 spring-tomcat-weaver.jar 拷貝到 Tomcat server/lib 子目錄。這個(gè)目錄包含的庫屬于 Tomcat 服務(wù)器私有,可以在 Spring 2 下載的 dist/weaver 目錄下找到 spring-tomcat-weaver.jar 庫。

          四、        提供商無關(guān)性

          開發(fā)者選擇JAVA平臺的一個(gè)最重要的原因就是它的提供廠商無關(guān)性。EJB 3.0是一個(gè)被設(shè)計(jì)為對提供商沒有依賴性的開放的標(biāo)準(zhǔn)。EJB 3.0規(guī)范由企業(yè)JAVA社區(qū)的主流開源組織和廠商共同編寫和支持的。EJB 3.0框架使開發(fā)者的應(yīng)用程序?qū)崿F(xiàn)可以獨(dú)立于應(yīng)用服務(wù)器。

          比如,JBossEJB 3.0的實(shí)現(xiàn)是基于Hibernate的,OracleEJB 3.0實(shí)現(xiàn)是基于TopLink的,但是,在JBoss或者Oracle上跑應(yīng)用程序,開發(fā)者既不需要去學(xué)習(xí)Hibernate,也不需要學(xué)習(xí)TopLink提供的獨(dú)特API。廠商無關(guān)性使EJB 3.0框架區(qū)別于當(dāng)前其他任何的POJO中間件框架。

          很多人認(rèn)為,盡管在任何應(yīng)用服務(wù)器都上可以使用Spring框架,但基于Spring的應(yīng)用仍然被限制于Spring本身,以及在應(yīng)用中使用到的Spring提供的各種特別服務(wù)。但事實(shí)上是不是如此呢?大家應(yīng)該知道,Spring的應(yīng)用程序中,JtaTransactionManager使用了自動檢測機(jī)制,不管是MBeans應(yīng)用服務(wù)器還是Tomcat應(yīng)用服務(wù)器。同理,當(dāng)使用JPA時(shí),Spring自動檢測persistence.xml文件,并且創(chuàng)建EntityManagerFactory對象。在上面這些機(jī)制中,Spring不管是采用注釋(如PersistenceContext@Transactional@Resource等等)還是采用XML(如”jee:indi-lookup”等等),都可以像EJB應(yīng)用一樣的與應(yīng)用服務(wù)器提供商無關(guān)。

          五、        小結(jié)

          筆者認(rèn)為,EJBSpring設(shè)計(jì)的角度根本不同,就目前來看,還不能說哪一個(gè)能完全打倒另外一個(gè)。首先EJB最初的設(shè)計(jì)思想考慮的是為分布式的應(yīng)用服務(wù)的。就因?yàn)檫@個(gè)原因,使得開發(fā)一個(gè)EJB不難,但是開發(fā)一個(gè)好的EJB卻非常難。此外對于中小型的應(yīng)用項(xiàng)目而言,基本不采用分布式的解決方案,那么為什么要采取一個(gè)為分布式設(shè)計(jì)的方案來解決非分布式的問題呢? Spring就是為了解決這個(gè)問題而誕生的。

          本文中,筆者希望比較客戶的評價(jià)Spring相對EJB所具有的一些特性,同時(shí),Spring可以與EJB進(jìn)行協(xié)同的工作,Spring可以應(yīng)用到EJB應(yīng)用中去,同樣,EJB可以在Spring應(yīng)用中很好的使用。同時(shí),Spring如今有力的支持注釋:@Resource@PersistenceContext@PostConstruct@PreDestroy@EJB@WebServiceRef。當(dāng)然,Spring 中不只是能使用Hibernate這樣的ORM框架,同樣可以使用JPA。更妙的是,Spring越來越與應(yīng)用服務(wù)器提供商無關(guān)了,很容易實(shí)現(xiàn)在不同的應(yīng)用服務(wù)中進(jìn)行移植。



          評論

          # re: Spring VS EJB 3 的若干認(rèn)識誤區(qū)  回復(fù)  更多評論   

          2008-01-30 13:32 by loocky
          文不對題

          # re: Spring VS EJB 3 的若干認(rèn)識誤區(qū)  回復(fù)  更多評論   

          2008-01-30 16:57 by 地球玩家
          JPA還不一樣要具體的ORM框架支撐,如Hibernate

          # re: Spring VS EJB 3 的若干認(rèn)識誤區(qū)  回復(fù)  更多評論   

          2008-02-17 12:55 by 93ttx
          不錯呀。好文章……

          # re: Spring VS EJB 3 的若干認(rèn)識誤區(qū)  回復(fù)  更多評論   

          2008-04-28 16:59 by BeanSoft
          截至到現(xiàn)在,Spring集團(tuán)正式投入EJB的懷抱了,嘿嘿。。。沒辦法呢,最后都要背靠Java EE掙大錢。

          # re: Spring VS EJB 3 的若干認(rèn)識誤區(qū)[未登錄]  回復(fù)  更多評論   

          2008-06-19 17:16 by 萬里
          哇噻 講的太好了........

          # re: Spring VS EJB 3 的若干認(rèn)識誤區(qū)[未登錄]  回復(fù)  更多評論   

          2008-06-19 17:17 by 萬里
          ^_^

          呵呵 好文章.........

          # re: Spring VS EJB 3 的若干認(rèn)識誤區(qū)[未登錄]  回復(fù)  更多評論   

          2009-04-13 21:08 by anna
          學(xué)習(xí)了

          # re: Spring VS EJB 3 的若干認(rèn)識誤區(qū)  回復(fù)  更多評論   

          2009-04-26 00:37 by springvsejb
          very good!

          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 通榆县| 沐川县| 于田县| 乐昌市| 西宁市| 德化县| 平陆县| 九龙坡区| 天气| 北宁市| 莲花县| 永州市| 达日县| 太仆寺旗| 紫金县| 年辖:市辖区| 集贤县| 大丰市| 新疆| 金湖县| 如皋市| 伊金霍洛旗| 陆河县| 桐城市| 邢台市| 湄潭县| 石狮市| 鄂托克前旗| 牙克石市| 格尔木市| 黎川县| 新乐市| 乐陵市| 专栏| 宁都县| 兴业县| 玉门市| 靖州| 沂源县| 宜州市| 金川县|