??xml version="1.0" encoding="utf-8" standalone="yes"?>麻豆成人久久精品二区三区红,中文字幕最新精品,精品91视频http://www.aygfsteel.com/Weibo-Forum/category/8719.html“道”就是指要自己才能走遍天下,“d”指两个直心(j)相对.zh-cnFri, 02 Mar 2007 06:37:04 GMTFri, 02 Mar 2007 06:37:04 GMT60Java Annotation入门http://www.aygfsteel.com/Weibo-Forum/archive/2006/04/13/40833.html微薄C֌微薄C֌Thu, 13 Apr 2006 03:16:00 GMThttp://www.aygfsteel.com/Weibo-Forum/archive/2006/04/13/40833.htmlhttp://www.aygfsteel.com/Weibo-Forum/comments/40833.htmlhttp://www.aygfsteel.com/Weibo-Forum/archive/2006/04/13/40833.html#Feedback0http://www.aygfsteel.com/Weibo-Forum/comments/commentRss/40833.htmlhttp://www.aygfsteel.com/Weibo-Forum/services/trackbacks/40833.html Java Annotation入门
作者:(x)cleverpig





版权声明Q本文可以自p{载,转蝲时请务必以超链接形式标明文章原始出处和作者信息及(qing)本声?/span>
作?cleverpig(作者的Blog:http://blog.matrix.org.cn/page/cleverpig)
原文:[http://www.matrix.org.cn/resource/article/44/44048_Java+Annotation.html]http://www.matrix.org.cn/resource/article/44/44048_Java+Annotation.html[/url]
关键?Java,annotation,标注


摘要Q?/span>
本文针对java初学者或者annotation初次使用者全面地说明?jin)annotation的用方法、定义方式、分cR初学者可以通过以上的说明制作简单的annotationE序Q但是对于一些高U的annotation应用Q例如用自定义annotation生成javabean映射xml文gQ还需要进一步的研究和探讨。涉?qing)到深入annotation的内容,作者将在后文《Java Annotation高应用》中谈到?br />
同时Qannotationq行存在两种方式Q运行时、编译时。上文中讨论的都是在q行时的annotation应用Q但在编译时的annotation应用q没有涉?qing)?br />
一、ؓ(f)什么用AnnotationQ?/span>

在JAVA应用中,我们帔RC些需要用模版代码。例如,Z(jin)~写一个JAX-RPC web serviceQ我们必L供一Ҏ(gu)口和实现作ؓ(f)模版代码。如果用annotation对远E访问的Ҏ(gu)代码q行修饰的话Q这个模版就能够使用工具自动生成?br />另外Q一些API需要用与E序代码同时l护的附属文件。例如,JavaBeans需要一个BeanInfo Class与一个Bean同时使用/l护Q而EJB则同样需要一个部|描q符。此时在E序中用annotation来维护这些附属文件的信息十分便利而且减少?jin)错误?br />
二、Annotation工作方式Q?/span>

?.0版之前的Javaq_已经h?jin)一些ad hoc annotation机制。比如,使用transient修饰W来标识一个成员变量在序列化子pȝ中应被忽略。而@deprecatedq个javadoc tag也是一个ad hoc annotation用来说明一个方法已q时。从Java5.0版发布以来,5.0q_提供?jin)一个正式的annotation功能Q允许开发者定义、用自qannoatationcd。此功能׃个定义annotationcd的语法和一个描qannotation声明的语法,dannotaion的APIQ一个用annotation修饰的class文gQ一个annotation处理工具QaptQ组成?br />annotationq不直接影响代码语义Q但是它能够工作的方式被看作cME序的工h者类库,它会(x)反过来对正在q行的程序语义有所影响。annotation可以从源文g、class文g或者以在运行时反射的多U方式被d?br />当然annotation在某U程度上使javadoc tag更加完整。一般情况下Q如果这个标记对java文产生影响或者用于生成java文的话Q它应该作ؓ(f)一个javadoc tagQ否则将作ؓ(f)一个annotation?br />
三、Annotation使用Ҏ(gu)Q?/span>

1。类型声明方式:(x)
通常Q应用程序ƈ不是必须定义annotationcdQ但是定义annotationcdq难事。Annotationcd声明于一般的接口声明极ؓ(f)cMQ区别只在于它在interface关键字前面用“@”符受?br />annotationcd的每个方法声明定义了(jin)一个annotationcd成员Q但Ҏ(gu)声明不必有参数或者异常声明;Ҏ(gu)q回值的cd被限制在以下的范_(d)(x)primitives、String、Class、enums、annotation和前面类型的数组Q方法可以有默认倹{?br />
下面是一个简单的annotationcd声明Q?br />清单1:

    /**
     * Describes the Request-For-Enhancement(RFE) that led
     * to the presence of the annotated API element.
     */
    public @interface RequestForEnhancement {
        int    id();
        String synopsis();
        String engineer() default "[unassigned]";
        String date();    default "[unimplemented]";
    }

代码中只定义?jin)一个annotationcdRequestForEnhancement?br />
2。修饰方法的annotation声明方式Q?/b>
annotation是一U修饰符Q能够如其它修饰W(如public、static、finalQ一般用。习(fn)惯用法是annotaions用在其它的修饰符前面。annotations由“@+annotationcd+带有括号的成?值列表”组成。这些成员的值必L~译时常量(卛_q行时不变)(j)?br />
AQ下面是一个用了(jin)RequestForEnhancement annotation的方法声明:(x)
清单2:

    @RequestForEnhancement(
        id       = 2868724,
        synopsis = "Enable time-travel",
        engineer = "Mr. Peabody",
        date     = "4/1/3007"
    )
    public static void travelThroughTime(Date destination) { ... }


BQ当声明一个没有成员的annotationcd声明Ӟ可用以下方式:(x)
清单3:

    /**
     * Indicates that the specification of the annotated API element
     * is preliminary and subject to change.
     */
    public @interface Preliminary { }


作ؓ(f)上面没有成员的annotationcd声明的简写方式:(x)
清单4:

    @Preliminary public class TimeTravel { ... }


CQ如果在annotations中只有唯一一个成员,则该成员应命名ؓ(f)valueQ?br />清单5:

    /**
     * Associates a copyright notice with the annotated API element.
     */
    public @interface Copyright {
        String value();
    }


更ؓ(f)方便的是对于h唯一成员且成员名为value的annotationQ如上文Q,在其使用时可以忽略掉成员名和赋值号Q?Q:(x)
清单6:

    @Copyright("2002 Yoyodyne Propulsion Systems")
    public class OscillationOverthruster { ... }


3。一个用实例:(x)
l合上面所讲的Q我们在q里建立一个简单的Zannotation试框架。首先我们需要一个annotationcd来表C某个方法是一个应该被试工具q行的测试方法?br />清单7:

    import java.lang.annotation.*;

    /**
     * Indicates that the annotated method is a test method.
     * This annotation should be used only on parameterless static methods.
     */
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface Test { }


值得注意的是annotaioncd声明是可以标注自qQ这L(fng)annotation被称为“meta-annotations”?br />
在上面的代码中,@Retention(RetentionPolicy.RUNTIME)q个meta-annotation表示?jin)此cd的annotation被虚拟Z留其能够在q行旉过反射被读取。而@Target(ElementType.METHOD)表示此类型的annotation只能用于修饰Ҏ(gu)声明?br />
下面是一个简单的E序Q其中部分方法被上面的annotation所标注Q?br />清单8:

    public class Foo {
        @Test public static void m1() { }
        public static void m2() { }
        @Test public static void m3() {
            throw new RuntimeException("Boom");
        }
        public static void m4() { }
        @Test public static void m5() { }
        public static void m6() { }
        @Test public static void m7() {
            throw new RuntimeException("Crash");
        }
        public static void m8() { }
    }

Here is the testing tool:

    import java.lang.reflect.*;

    public class RunTests {
       public static void main(String[] args) throws Exception {
          int passed = 0, failed = 0;
          for (Method m : Class.forName(args[0]).getMethods()) {
             if (m.isAnnotationPresent(Test.class)) {
                try {
                   m.invoke(null);
                   passed++;
                } catch (Throwable ex) {
                   System.out.printf("Test %s failed: %s %n", m, ex.getCause());
                   failed++;
                }
             }
          }
          System.out.printf("Passed: %d, Failed %d%n", passed, failed);
       }
    }


q个E序从命令行参数中取出类名,q且遍历此类的所有方法,试调用其中被上面的试annotationcd标注q的Ҏ(gu)。在此过E中Z(jin)扑և哪些Ҏ(gu)被annotationcd标注q,需要用反的方式执行此查询。如果在调用Ҏ(gu)时抛出异常,此方法被认ؓ(f)已经p|Qƈ打印一个失败报告。最后,打印q行通过/p|的方法数量?br />下面文字表示?jin)如何运行这个基于annotation的测试工P(x)

清单9:

    $ java RunTests Foo
    Test public static void Foo.m3() failed: java.lang.RuntimeException: Boom
    Test public static void Foo.m7() failed: java.lang.RuntimeException: Crash
    Passed: 2, Failed 2


四、Annotation分类Q?/span>

Ҏ(gu)a(chn)nnotation的用方法和用途主要分Z下几c:(x)

1。内建Annotation——Java5.0版在java语法中经常用到的内徏AnnotationQ?/b>
@Deprecated用于修饰已经q时的方法;
@Override用于修饰此方法覆盖了(jin)父类的方法(而非重蝲Q;
@SuppressWarnings用于通知java~译器禁止特定的~译警告?br />
下面代码展示?jin)内建Annotationcd的用法:(x)
清单10:

package com.bjinfotech.practice.annotation;

/**
* 演示如何使用java5内徏的annotation
* 参考资料:(x)
* http://java.sun.com/docs/books/tutorial/java/javaOO/annotations.html
* http://java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html
* http://mindprod.com/jgloss/annotations.html
* @author cleverpig
*
*/
import java.util.List;

public class UsingBuiltInAnnotation {
        //食物c?br />        class Food{}
        //q草c?br />        class Hay extends Food{}
        //动物c?br />        class Animal{
                Food getFood(){
                        return null;
                }
                //使用Annotation声明DeprecatedҎ(gu)
                @Deprecated
                void deprecatedMethod(){
                }
        }
        //马类-l承动物c?br />        class Horse extends Animal{
                //使用Annotation声明覆盖Ҏ(gu)
                @Override
                Hay getFood(){
                        return new Hay();
                }
                //使用Annotation声明止警告
                @SuppressWarnings({"deprecation","unchecked"})
                void callDeprecatedMethod(List horseGroup){
                        Animal an=new Animal();
                        an.deprecatedMethod();
                        horseGroup.add(an);
                }
        }
}


2。开发者自定义AnnotationQ由开发者自定义Annotationcd?/b>
下面是一个用annotationq行Ҏ(gu)试的sampleQ?br />
AnnotationDefineForTestFunctioncd定义如下Q?br />清单11:

package com.bjinfotech.practice.annotation;

import java.lang.annotation.*;
/**
* 定义annotation
* @author cleverpig
*
*/
//加蝲在VM中,在运行时q行映射
@Retention(RetentionPolicy.RUNTIME)
//限定此annotation只能标示Ҏ(gu)
@Target(ElementType.METHOD)
public @interface AnnotationDefineForTestFunction{}


试annotation的代码如下:(x)

清单12:

package com.bjinfotech.practice.annotation;

import java.lang.reflect.*;

/**
* 一个实例程序应用前面定义的AnnotationQAnnotationDefineForTestFunction
* @author cleverpig
*
*/
public class UsingAnnotation {
        @AnnotationDefineForTestFunction public static void method01(){}
        
        public static void method02(){}
        
        @AnnotationDefineForTestFunction public static void method03(){
                throw new RuntimeException("method03");
        }
        
        public static void method04(){
                throw new RuntimeException("method04");
        }
        
        public static void main(String[] argv) throws Exception{
                int passed = 0, failed = 0;
                //被检的cd
                String className="com.bjinfotech.practice.annotation.UsingAnnotation";
                //逐个(g)查此cȝҎ(gu)Q当其方法用annotation声明时调用此Ҏ(gu)
            for (Method m : Class.forName(className).getMethods()) {
               if (m.isAnnotationPresent(AnnotationDefineForTestFunction.class)) {
                  try {
                     m.invoke(null);
                     passed++;
                  } catch (Throwable ex) {
                     System.out.printf("试 %s p|: %s %n", m, ex.getCause());
                     failed++;
                  }
               }
            }
            System.out.printf("试l果Q?通过: %d, p|Q?%d%n", passed, failed);
        }
}


3。用第三方开发的Annotationcd
q也是开发h员所常常用到的一U方式。比如我们在使用Hibernate3.0时就可以利用Annotation生成数据表映配|文Ӟ而不必用Xdoclet?br />
五、ȝQ?/span>

1。前面的文字说明?jin)annotation的用方法、定义方式、分cR初学者可以通过以上的说明制作简单的annotationE序Q但是对于一些高U的annotation应用Q例如用自定义annotation生成javabean映射xml文gQ还需要进一步的研究和探讨?br />
2。同Ӟannotationq行存在两种方式Q运行时、编译时。上文中讨论的都是在q行时的annotation应用Q但在编译时的annotation应用q没有涉?qing),因?f)~译时的annotation要用annotation processing tool?br />
涉及(qing)以上2斚w的深入内容,作者将在后文《Java Annotation高应用》中谈到?br />
六、参考资源:(x)
·Matrix-Java开发者社?http://www.matrix.org.cn
·http://java.sun.com/docs/books/tutorial/java/javaOO/annotations.html
·http://java.sun.com/j2se/1.5.0/docs/guide/apt/GettingStarted.html
·http://java.sun.com/j2se/1.5.0/docs/guide/apt/GettingStarted.html
·http://java.sun.com/j2se/1.5.0/docs/guide/apt/GettingStarted.html
·作者的Blog:http://blog.matrix.org.cn/page/cleverpig


微薄C֌ 2006-04-13 11:16 发表评论
]]>
Spring与EJB3.0的比?/title><link>http://www.aygfsteel.com/Weibo-Forum/archive/2006/03/03/33395.html</link><dc:creator>微薄C֌</dc:creator><author>微薄C֌</author><pubDate>Fri, 03 Mar 2006 02:53:00 GMT</pubDate><guid>http://www.aygfsteel.com/Weibo-Forum/archive/2006/03/03/33395.html</guid><wfw:comment>http://www.aygfsteel.com/Weibo-Forum/comments/33395.html</wfw:comment><comments>http://www.aygfsteel.com/Weibo-Forum/archive/2006/03/03/33395.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/Weibo-Forum/comments/commentRss/33395.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/Weibo-Forum/services/trackbacks/33395.html</trackback:ping><description><![CDATA[<P>摘要:<BR>Spring框架虽然很流行但q不是一个标准的开源框架。EJB3.0是由Java Community Process (JCP)制订的标准框?q两个框架结构都有一个共同核?j)设计理念?x)中间g服务传递给耦合松散的POJOS (Plain Old Java Objects, 单洁净Java对象)?本文对Srping和EJB3.0框架背后的关键不同处q行考察Qƈ讨论其优~点。本文的观点也适用于其它更ؓ(f)人知的框Ӟ因ؓ(f)他们都是对“耦合松散的POJO”的设计 <BR>POJO应用框架QSpring与EJB3.0的比?/P> <P><BR>作者:(x)Michael Juntao Yuan</P> <P><BR>06/29/2005</P> <P><BR>译Qloryliu</P> <P><BR>版权声明Q可以Q意{载,转蝲时请务必以超链接形式标明文章原始出处和作者信息及(qing)本声?BR>英文原文地址:<BR><A >http://www.onjava.com/pub/a/onjava/2005/06/29/spring-ejb3.html</A><BR>中文地址:<BR><A >http://www.matrix.org.cn/resource/article/43/43718_Spring_EJB.html</A><BR>关键词:(x) Spring EJB</P> <P> </P> <P>艾伯?爱因斯坦曄说过Q“一切都应该可能地单,但是不能更简单。”确实如此,化一门理论的基本假设Q我们可以专注于真正关键的地方Q这正是一直以来对U学真理的追求。企业Y件开发同样如此?/P> <P>提供一个将复杂的事物(例如Q事务、安全或持久性)(j)对开发者进行隐藏的应用框架是简化企业Y件开发的关键。一个设计良好的框架可以提高代码重用率、开发者的生力及(qing)软g的质量。然而,现有J2EE1.4的EJB2.1框架被普遍认计差Q且q于复杂。不满于EJB2.1的框架结构,Java开发者尝试了(jin)各种各样的中间g服务传递方法。最引h注目的是Q以下两个框架引起了(jin)开发者极大兴ƈ得到?jin)大量正面的反馈。他们以未来企业Java应用所选框架的姿态展现?/P> <P>        Spring框架虽然很流行但q不是一个标准的开源框架。它主要由Interface21 Inc开发和控制。Spring框架l构是基于依赖注?Dependency Injection (DI))的设计模式。它可以独立或在现有的应用服务器上运行,而且大量C用了(jin)xml配置文g</P> <P>        EJB3.0是由Java Community Process (JCP)制订的标准框Ӟ为所有主要的J2EE厂商支持。JBoss已经提供?jin)试用版EJB3.0标准的开源或商业性质实现。EJB3.0充分利用?jin)Java的注?/P> <P>q两个框架结构都有一个共同核?j)设计理念?x)中间g服务传递给耦合松散的POJOS (Plain Old Java Objects, 单洁净Java对象)?q样的框架利用截取执行上下文或在q行时将服务对象注入POJO来把应用服务“缠l”到POJO。POJO本nq不兛_(j)q种“缠l”,对这U框架结构也没有什么依赖。因此,开发者可专注于业务逻辑和脱L架的POJO单元试。除此之外, ׃POJOq不要l承框架的类或实现其接口Q开发者能够极其灵zd搭徏l承l构和徏造应用?/P> <P>然而,在拥有同一理念的同Ӟ两个框架l构使用不同的方式来传递POJO服务。许多书c或文章都将Spring 或EJB3.0和EJB2.1做了(jin)比较Q但是对Spring 和EJB3.0的比较ƈ没有仔细研究q。在本文中,我将对Srping和EJB3.0框架背后的关键不同处q行考察Qƈ讨论其优~点。本文的观点也适用于其它更ؓ(f)人知的框Ӟ因ؓ(f)他们都是对“耦合松散的POJO”的设计。希望这文章可以帮助你选择适合你需求的最好框架?/P> <P>厂商无关?BR>开发者选择Javaq_其中最引h注目的理׃一Q厂商无x。EJB3.0正是一套设计ؓ(f)厂商无关的开放性标准。EJB3.0标准为所有企业JavaC֛里开源或商业性质厂商所开发和支持。它?yu)开发者与应用服务器实现完全隔R例如,JBoss?EJB3.0实现ZHibernateQOracle的基于TopLinkQ但是开发者ƈ不须要学?fn)Hibernate- 或TopLink的具体API来应用可在Jboss或Oracle上运行。厂商无xEJB3.0与现今其它POJO中间件框架区别开来?/P> <P>但是Q正如许多EJB3.0评论家迅速所指出的,在本文撰写时EJB3.0标准q没有到达一个最l版本。大概还有一Cq的旉EJB3.0才能q泛Cؓ(f)所有主要J2EE厂商所支持。即使你的应用服务器本n不支持EJB3.0Q你仍然可以通过下蝲安装”内嵌的”EJB3.0产品来运行EJB3.0的应用。例如,JBoss的内嵌EjB3.0是开源品且可以在Q何J2SE5.0兼容的环境运?例如, 在Q何Java服务器上)Q此产品正处于Y件测试阶Dc(din)其它厂商不久也发布自q内嵌EJB3.0产品Q特别是针对标准中关于数据持久性的部分?/P> <P>另一斚wQSpring一直以来都是非标准的技术,在未来可预知的一D|间内q种情况持l下厅R虽然你可以在Q何应用服务器上用Spring框架QSpring应用?x)被锁入在Spring本n和你选择整合qSpring的具体服务中?/P> <P>        Spring框架是一个开源项目,但同时它有一个XML格式的配|文件和~程接口。当然Q何一个非标准的品都?x)有q种“锁入?lock-in)的情况,q不是SpringҎ(gu)的。但Spring应用的长期生存能力仍然还得托Springq个目的福Q或者是Interface21公司Q它雇䄦?jin)大部分Spring核心(j)开发h员)(j)。除此之外,假如你用CQ何一个具体的Spring服务Q例如,Spring事务理器或则Spring MVCQ你也会(x)被锁入到q些API里?BR>        Spring的应用对l端用户是不可知的。例如,Ҏ(gu)据持久服务,Spring框架兼容不同的DAO和JDBC的模版帮助类Q如Hibernate, iBatis, ?JDO。所以假如你需要ؓ(f)spring应用切换在数据持久化服务Q例如从JBDC到HibernateQ,你需要修改你的代码以适合新的模版帮助cR?/P> <P>服务整合<BR>从一个很高的角度上看QSpring框架处于应用服务器和服务库的上方。服务整合的代码Q如Q数据访问模板和帮助c)(j)属于框架Qƈ暴露于应用开发者。相反,EJB3.0框架与应用服务器高度整合Q服务整合代码也包装在一个标准接口后面?/P> <P>因此Q实现EJB3.0的厂商可以大大地优化整体性能和提升开发者的体验。例如,在JBoss EJB3.0的实CQ当你在用EntityManager持久化一个Entity BeanӞ后台的Hibernate?x)话事务已经自动地帮定到调用?gu)的JTA 的事务上Q在JTA 事务提交的同时Hibernate?x)话事务也提交?jin)。你甚至可以使用一个简单的 @PersistenceContext 注释Q稍候例子演C)(j)EntityManager和它后台的Hibernate事务l定C个stateful session bean的应用事务中。在一个会(x)话中应用事务横跨多个U程Q这在事务性网应用很有用Q例如,多页面的购物车?BR>׃高度整合的EJB3.0的框Ӟ使简单、集成的~程接口成ؓ(f)可能。Oracle EJB3.0框架和其后台的Toplink持久化服务也同样E度地整合?/P> <P>另一个EJB3.0整合服务的绝好例子就是集支持。假如你在一个服务器集群上部|了(jin)一个EJB3.0的应用,所有容?fail-over)、负载均衡、分布式~冲和状态复刉已经自动为应用所获得可用。后台的集群支持被隐藏在EJB3.0的框架后面,对EJB3.0开发者来说这些都是完全透明不可见的?/P> <P>在Spring里,很难优化框架和服务之间的通讯。例如,Z(jin)使用Spring里的声明事务服务来管理Hibernate事务Q你必须昄地在XML文g中配|Spring TransactionManager和Hibernate SessionFactory对象。Spring必须甉|C地理横跨多个HTTPh的事务。除此之外,没有别的Ҏ(gu)均衡Spring应用里的集群?/P> <P>服务l合的弹?BR>׃Spring的服务整合代码作为编E接口的一部䆾暴露在外Q应用开发者有按自己需求装配服务的Ҏ(gu)。这个特点你能够组合自q轻量U应用服务器。Spring的一个普遍用法就是将Tomcat和Hibernatel合在一h持数据库驱动的web应用。在q种情况QSpring本n提供事务服务QHibernat提供持久化服务——这U设|创Z(jin)一个袖珍型的应用服务器?/P> <P>EJB3.0应用服务器典型地不提供这U根据需求Q你挑捡服务的Ҏ(gu)空间。大多数旉Q你得到的只是一pd包装好的Ҏ(gu),其中一些你可能Ҏ(gu)׃需要。但是如果应用服务器像JBoss一h供一个模块性的内部设计Q那么你可以只取其中一部分Q而把不必要的部分剥去。在M情况Q去自定义一个功能强大的应用服务器是没有什么h(hun)值的?/P> <P>当然Q假如应用已l超q单个点Q那么你应该加入常用服务器上的服务,例如Q资源池Qresource poolingQ,消息队列Qmessage queuingQ和集群QclusteringQ。就M的资源消耗而言QSpring解决Ҏ(gu)和其他EJB3.0解决Ҏ(gu)一h重量U的?/P> <P>在Spring框架里,hҎ(gu)的服务装配使得虚拟对象而不是真正的业务对象l定到应用中做脱d器的单元试更简单。在EJB3.0应用中,大多数组仉是简单POJOQ他们可以很Ҏ(gu)地在容器外被试。但是对于与容器服务相关的对象(例如持久化实实体理器EntityManagerQ徏议用容器内测试。因样会(x)比虚拟对象测试方法更单,强壮?qing)准?/P> <P>XML Vs.注解<BR>从应用开发者的观点上来看,Spring的编E开发接口主要基于XML配置文g而EJB3.0q泛地应用Java注解。XML可以表达复杂的关p,但是它也冗长且不够健壮;注解单明?jin),但是很难在注解里表达复杂或承性的关系?/P> <P>Spring选择XML或EJB3.0选择注解都是有他们两者框架后的体pȝ构决定的。因为注解只能容U_的配置信息Q只有整合前的框Ӟ重头戏都在框枉Q才可以把广泛地使用注解作ؓ(f)配置选择。正如我们所讨论q的QEJB3.0刚好W合q个要求Q而Spring作ؓ(f)一个普通的DI框架q不W合?</P> <P>当然QEJB3.0和Spring都相互取长补短,在某U程度上他们都支持XML和注解。例如,在EJB3.0中,XML配置文g作ؓ(f)一个可选的重蝲机制来改变注解的默认行ؓ(f)。注解也可以配置一些Spring服务?/P> <P>通过例子是学?fn)XML和注解方式之间差异的最好方法。在下面几个环节里,让我们来看看Spring和EJB3.0是怎样提供关键服务l应用的?/P> <P>声明性服?BR>Spring和EJB3.0都将q行时服务(例如Q事务、安全、日志和配置服务Q绑定到应用。因些服务于应用的业务逻辑是没有直接联p,他们只是由应用本w管理。换句话_(d)q些服务在运行时由容器透明地应用到应用中。开发者或是管理者配|容器,准确地告诉它什么时候怎样应用q些服务?/P> <P>EJB3.0q用Java注解来配|声明性服务,而Sring使用XML配置文g。在大多数情况下QEJB3.0注解方式对于q种服务更简单明?jin)。这里有一个在EJB3.0中将事务服务q用到POJO的例子?/P> <P>public class Foo {        @TransactionAttribute(TransactionAttributeType.REQUIRED)    public bar () {      // do something ...    }    }</P> <P>你也可以Z个代码段声明多个属性,应用多个服务。这是一个在EJB3.0里同时应用事务和安全服务到POJO的例子?/P> <P>@SecurityDomain("other")public class Foo {        @RolesAllowed({"managers"})    @TransactionAttribute(TransactionAttributeType.REQUIRED)    public bar () {      // do something ...    }   }</P> <P>使用XML说明代码属性和配置声明性服务会(x)D冗长和不E_的配|文件。下面是一个在Spring应用中的XML片段Q其应用一个非常简单的Hibernate事务到方法Foo.bar()中?/P> <P><!-- Setup the transaction interceptor --><bean id="foo"   class="org.springframework.transaction        .interceptor.TransactionProxyFactoryBean">        <property name="target">        <bean class="Foo"/>    </property>        <property name="transactionManager">        <ref bean="transactionManager"/>    </property>        <property name="transactionAttributeSource">        <ref bean="attributeSource"/>    </property></bean><!-- Setup the transaction manager for Hibernate --><bean id="transactionManager"   class="org.springframework.orm         .hibernate.HibernateTransactionManager">        <property name="sessionFactory">        <!-- you need to setup the sessionFactory bean in              yet another XML element -- omitted here -->        <ref bean="sessionFactory"/>    </property></bean><!-- Specify which methods to apply transaction --><bean id="transactionAttributeSource"  class="org.springframework.transaction         .interceptor.NameMatchTransactionAttributeSource">      <property name="properties">        <props>            <prop key="bar">        </props>    </property></bean></P> <P>XML的复杂度?x)以几何U数增长Q如果你向同一个POJOd更多的拦截器(interceptors)Q例如安全拦截器Q。意识到只有XML配置文g的局限,Spring使用Apache Commons 元数据在Java源码中来说明事务属性。最新版本的Spring1.2也支持JDK-1.5风格注解。要使用事务元数据,你须要将上面的transactionAttributeSourc bean变成一个AttributesTransactionAttributeSource实例。ƈ为元数据拦截器添加额外邦定?/P> <P>    class="org.springframework.aop.framework.autoproxy           .DefaultAdvisorAutoProxyCreator"/><bean id="transactionAttributeSource"    class="org.springframework.transaction.interceptor           .AttributesTransactionAttributeSource"    autowire="constructor"/><bean id="transactionInterceptor"    class="org.springframework.transaction.interceptor           .TransactionInterceptor"    autowire="byType"/><bean id="transactionAdvisor"    class="org.springframework.transaction.interceptor           .TransactionAttributeSourceAdvisor"    autowire="constructor"/><bean id="attributes"    class="org.springframework.metadata.commons           .CommonsAttributes"/></P> <P>当你有很多事务性方法时QSpring元数据可以简化transactionAttributeSource。但是这q没有解决XML配置文g的根本问题。冗长而又J琐的事务拦截器, transactionManager,和transactionAttributeSource仍然需要?/P> <P>依赖注入(Dependency Injection, DI)</P> <P>中间件容器的一个关键好处之一是它可以让开发者徏造一个关p耦合松散的应用。服务端客户只需要知道服务的接口。容器依据具体的实现实例化服务对象,使他们ؓ(f)客户端所用。在不改变接口和客户端代码的情况下,q得容器可以在多种服务实现之间切换?/P> <P>依赖注入的模式是实现耦合松散应用的最好方法之一。它更易用,比其他方法也明了(jin)多了(jin)Q比如通过JNDI依赖性查询或容器回调。用DIQ框架就像一个对象工厂,它创建服务对象然后按照运行时配置这些服务对象注入到应用的POJO里。站在应用开发者的角度Q客L(fng)POJO在被使用时可自动获得正确的服务对象?/P> <P>Spring和EJB3.0都提供广泛的DI模式支持。但是他们之间仍存在很大的不同之处。Spring支持一般意义上且复杂的DI APIQ其ZXML配置文g。EJB3.0支持大多数普通服务对象(如EJB?qing)context对象Q的注入和Q何简单注解的JDNI?</P> <P>EJB63.0注解非常单易用。@Resource 标记表示注入大多数普通服务对象和JDNI对象。以下例子展CZ(jin)怎样把服务的JDNI的默认DataSource 对象注入到POJO的一个属性变量中。DefaultDS是DataSource.的JDNI名字。MyDb变量在第一ơ被使用时被赋上?jin)正的倹{?/P> <P>public class FooDao {    @Resource (name="DefaultDS")    DataSource myDb;        // Use myDb to get JDBC connection to the database}</P> <P>除了(jin)直接属性变量注入,Ejb3.0的@Resource注解也可以用来在setterҎ(gu)里面注入对象。例如,下面的例子就是注入session context对象。应用从不会(x)昄地调用setterҎ(gu)Q其在其他方法被调用前由容器来触发?/P> <P>@Resource public void setSessionContext (SessionContext ctx) {     sessionCtx = ctx; } </P> <P>针对更复杂的服务对象Q定义了(jin)专用的注入注解。例如,@EJB注释用来注入EJB的StubQ@PersistenceContext注解用来注入处理EJB3.0实体bean讉K数据库的EntityManager对象。下面是一个怎样EntityManager对象注入有状态的 session bean的例子。@PersistenceContext的type属性具体说明了(jin)被注入的EntityManager有一个扩展的事务transaction context。transaction contextq不?x)同JTA transaction manager一赯动提交。因此它可以用在在一个会(x)话横跨多个线E的应用事务中?/P> <P>@Statefulpublic class FooBean implements Foo, Serializable {    @PersistenceContext(      type=PersistenceContextType.EXTENDED    )    protected EntityManager em;        public Foo getFoo (Integer id) {        return (Foo) em.find(Foo.class, id);    }}</P> <P>EJB3.0标准通过注解可以被注入的服务器资源。但是它q支持将用户定义的应用POJO之间的相互注入?/P> <P>在Spring中,首先你必Mؓ(f)POJO中的服务对象定义一个setterҎ(gu)。下面的例子说明POJO需要一个Hibernate session 的引?/P> <P>public class FooDao {        HibernateTemplate hibernateTemplate;        public void setHibernateTemplate (HibernateTemplate ht) {        hibernateTemplate = ht;    }        // Use hibernateTemplate to access data via Hibernate    public Foo getFoo (Integer id) {        return (Foo) hibernateTemplate.load (Foo.class, id);    }}</P> <P>然后Q以XML里的元素作ؓ(f)桥梁具体描述容器怎样在运行时得到服务对象q将其注入到POJO里。以下是一个XML例子Q具体描qC(jin)一个数据源l定C个Hibernate session factoryQ然后从Hibernate session factory到Hibernate template objectQ最后从template object到应用的POJO。Spring代码如此复杂的部分原因是因ؓ(f)我们L手动注入后台Hibernate plumbing objects。而EJB3.0 EntityManager是自动被服务器管理和配置。这又将我们带回到Springq不像EJB3.0那样高度与服务整合的论点上?/P> <P><bean id="dataSource"   class="org.springframework         .jndi.JndiObjectFactoryBean">    <property name="jndiname">        <value>java:comp/env/jdbc/MyDataSource</value>    </property></bean><bean id="sessionFactory"   class="org.springframework.orm         .hibernate.LocalSessionFactoryBean">    <property name="dataSource">        <ref bean="dataSource"/>    </property></bean><bean id="hibernateTemplate"   class="org.springframework.orm         .hibernate.HibernateTemplate">    <property name="sessionFactory">        <ref bean="sessionFactory"/>    </property>    </bean><bean id="fooDao" class="FooDao">    <property name="hibernateTemplate">        <ref bean="hibernateTemplate"/>    </property></bean><!-- The hibernateTemplate can be injected        into more DAO objects --></P> <P>虽然QSpring里基于XML的依赖注入语法复杂,但却功能强大。你可以Q何POJO注入到另一个POJOQ包括你自己在应用定义的那些POJO。假如你惛_EJB3.0应用中用Spring的DI功能 Q你可以通过JNDI把一个Spring bean factory注入到EJB。在一些EJB3.0的应用服务器里,厂商可能?x)额外定义非标准的POJO注入API。一个很好的例子是JBoss MicroContainer。它比Spring更一般化Q因为它处理Aspect-Oriented ProgrammingQAOPQ的依赖?/P> <P>l论</P> <P>Spring和Ejb3.0虽然都是Z(jin)向企业服务提供耦合松散的POJOQ但是用了(jin)不同Ҏ(gu)来达到这个目的。两者都大量C用了(jin)依赖注入?/P> <P>对于EJB3.0Q基于标准的Ҏ(gu)、注解的q泛使用、与应用服务器的高度整合都得EJB3.0拥有更好的厂商无x,更高的开发效率。依赖注入和集中的XML配置文g协调一致的使用使开发者能够构建更有弹性的应用Qƈ且可以同时和几个应用服务提供者一起协作?/P> <P>鸣谢<BR>作者感谢tephen Chambers,、ill Burke、Andy Oliver的珍贉|见?/P> <P>资源<BR>Spring框架(参见CodeZoo: Spring) <BR>EJB 3.0 <BR>JBoss EJB 3.0 <BR>Oracle Application Server EJB 3.0 Preview </P> <P>Michael Juntao Yuan 善长于提供end-to-end的企业解x案, 也是一个移动方面的专家Q是avidq个开源项目的支持者?/P><img src ="http://www.aygfsteel.com/Weibo-Forum/aggbug/33395.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/Weibo-Forum/" target="_blank">微薄C֌</a> 2006-03-03 10:53 <a href="http://www.aygfsteel.com/Weibo-Forum/archive/2006/03/03/33395.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>J2EE架构?个最?jng)_?/title><link>http://www.aygfsteel.com/Weibo-Forum/archive/2006/03/03/33393.html</link><dc:creator>微薄C֌</dc:creator><author>微薄C֌</author><pubDate>Fri, 03 Mar 2006 02:49:00 GMT</pubDate><guid>http://www.aygfsteel.com/Weibo-Forum/archive/2006/03/03/33393.html</guid><wfw:comment>http://www.aygfsteel.com/Weibo-Forum/comments/33393.html</wfw:comment><comments>http://www.aygfsteel.com/Weibo-Forum/archive/2006/03/03/33393.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/Weibo-Forum/comments/commentRss/33393.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/Weibo-Forum/services/trackbacks/33393.html</trackback:ping><description><![CDATA[<P>--利用高J2EE最?jng)_跉|改善现有和将来的J2EE应用E序的架构和设计<BR>虽然许多文章曄讨论qJ2EE最?jng)_c(din)那么,Z么我q要再写一文章呢Q本文究竟与以前的文章有何不同或者说比其他文章好在哪呢?<BR>  首先Q本文的目标读者是正在从事技术工作的架构师。ؓ(f)?jin)避免浪费大家的才智Q我?x)避免讲qC些陈腐的最?jng)_践,例如“日常构建(build dailyQ”、“测试一切(test everythingQ”和“经帔R成( integrate oftenQ?MhU职架构师的目都有分工明确的、定义良好的团队l构。他们还行编码检查、构Z码(每日或在需要时Q、进行测试(单元、集成和pȝ的)(j)、部|和配置/释放理而具备已记录的过E?BR>  其次Q我蟩q通常Ҏ(gu)的最?jng)_践,例如“基于接口的设计”、“用著名的设计模型”以?qing)“用面向服务的架构”等。相反,我将集中讲述我曾学过q且使用?jin)若q年?Q不是很多)(j)个方面的in-the-trench评。最后,本文的目的是让?zhn)思考一下自q架构Q提供工作代码示例或者解x案超Z(jin)本文的范围。下面就让我介绍一下这6课:(x)</P> <P>W?课:(x)切勿l过服务器端验证<BR>  作ؓ(f)一位Y仉问,我曾有机?x)不但设计ƈ实现了(jin)Web应用E序Q而且q评?审核?jin)许多Web应用E序。在复杂的、ƈ且用JavaScript客户端封装的应用E序内,我经帔R到对用户输入信息执行大量(g)查的Web面。即使HTML元素h数据有效性的属性也如此Q例如MAXLENGTH。只有在成功验证所有输入信息后Q才能提交HTML表单。结果,一旦服务器端收到通知表单Q请求)(j)Q便恰当地执行业务逻辑?BR>  在此Q?zhn)发现问题了(jin)么Q开发h员已l做?jin)许多重要的假设。例如,他们假设所有的Web应用E序用户都同栯实。开发h员还假设所有用户将L使用他们试q的览器访问Web应用E序。还有很多其他的假设。这些开发h员忘C(jin)利用可以免费得到的工P通过命o(h)行很Ҏ(gu)地模拟类似浏览器的行为。事实上Q通过在浏览器H口中键入适当的URLQ?zhn)可以发送Q何“posted”表单,管如此Q通过用q些面的GEThQ?zhn)很容易地Lq样的“表单发送”。但是,(zhn)不能阻止h们模拟甚臛_Z们自q览器来入R(zhn)的pȝ?BR>Ҏ(gu)的问题在于开发h员不能确定客L(fng)验证与服务器端验证的主要差别。两者的主要差别不在于验证究竟发生在哪里Q例如在客户端或者在服务器端。主要的差别在于验证背后的目的不同?BR>  客户端验证仅仅是方便。执行它可ؓ(f)用户提供快速反馈——应用E序g做出响应Q给ZU运行桌面应用程序的错觉?BR>  另一斚wQ服务器端验证是构徏安全Web应用E序必需的。不在客户端一侧输入的是什么,它可以确保客L(fng)送往服务器的所有数据都是有效的?BR>  因而,只有服务器端验证才可以提供真正应用程序的安全。许多开发h员陷入了(jin)错误感觉的圈套:(x)只有在客L(fng)q行所有数据的验证才能保安全。下面是说明此观点的一个常见的CZQ?BR>  一个典型的d面拥有一个用来输入用户名的文本框和一个输入密码的文本框。在服务器端Q某人在接收servlet中可能遇C些代码,q些代码构成?jin)下面Ş式的SQL查询Q?BR>"SELECT * FROM SecurityTable WHERE username = '" + form.getParameter("username") + "' AND password = '" + form.getParameter("password") + "';"Qƈ执行q些代码。如果查询在l果集的某一行返回,则用L(fng)录成功,否则用户dp|?BR>  W一个问题是构造SQL的方式,但现在让我们暂时忽略它。如果用户在用户名中输入“Alice'--”会(x)怎样呢?假设名ؓ(f)“Alice”的用户已经在SecurityTable中,q时此用P更恰当的说法是黑客)(j)成功地登录。我把扑ևZ么会(x)出现q种情况的原因做为留l?zhn)的一道习(fn)题?BR>  许多创造性的客户端验证可以阻止一般的用户从浏览器中这L(fng)录。但对于已经用?jin)JavaScript的客L(fng)Q或者那些能够用其他类似浏览器E序直接发送命令(HTTP POST和GET命o(h)Q的高用户Q或者说黑客Q来_(d)我们又有什么办法呢Q服务器端验证是防止q种漏洞cd所必须的。这ӞSSL、防火墙{都z不上用Z(jin)?/P> <P>W?课:(x)安全q是附加物<BR>  如第1课所qͼ我曾有幸研究q许多Web应用E序。我发现所有的JavaServer PageQJSPQ都有一个共同的主题Q那是hcM下面伪代码的布局Q?/P> <P><%<BR>User user = <BR>session.getAttribute("User");<BR>if(user == null)<BR>{<BR>// redirect to <BR>// the logon page?BR>} <BR>if(!user.role.equals("manager"))<BR>{<BR>// redirect to the<BR>// "unauthorized" page?BR>}<BR>%><BR><!-<BR>HTML, JavaScript, and JSP<BR>code to display data and<BR>allow user interaction --></P> <P>  如果目使用诸如Strutsq样的MVC框架Q所有的Action Bean都会(x)hcM的代码。尽最后这些代码可能运行得很好Q但如果(zhn)发C个bugQ或者?zhn)必须d一个新的角Ԍ例如Q“guest”或者“admin”)(j)Q这׃(x)代表一场维护恶梦?BR>  此外Q所有的开发h员,不管(zhn)多q轻Q都需要熟(zhn)这U编码模式。当?dng)?zhn)可以用一些JSP标签来整理JSP代码Q可以创Z个清除派生Action Bean的基本Action Bean。尽如此,׃与安全相关的代码?x)分布到多个地方Q所以维护时的恶梦仍旧存在。由于Web应用E序的安全是建立在应用程序代码的U别上(由多个开发h员)(j)Q而不是徏立在架构U别上,所以Web应用E序q是很可能存在弱炏V?BR>  很可能,Ҏ(gu)的问题是在项目接q完成时才处理安全性问题。最q作Z名架构师Q我曑֜一q多的时间里亲历?jin)某一要实现项目的6个版本,而直到第四版时我们才提到?jin)安全性——即使该目?x)将高度敏感的个人数据暴露于Web上,我们也没有注意到安全性。ؓ(f)?jin)更改发布计划,我们卷入了(jin)与目资助人?qing)其管理h员的争斗中,以便在第一版中包含所有与安全相关的功能,q将一些“业务”功能放在后l的版本中。最l,我们赢得?jin)胜利。而且׃应用E序的安全性相当高Q能够保护客L(fng)U有数据Q这一Ҏ(gu)们引以ؓ(f)荣,我们的客户也非常高兴?BR>  遗憾的是Q在大多数应用程序中Q安全性看hq未增加M实际的商业h(hun)|所以直到最后才解决。发生这U情冉|Qh们才匆忙开发与安全相关的代码,而丝毫没有考虑解决Ҏ(gu)的长期可l护性或者健壮性。忽视该安全性的另一个征兆是~Z全面的服务器端验证,如我在第1课中所qͼq一Ҏ(gu)安全Web应用E序的一个重要组成部分?BR>  CQJ2EE Web应用E序的安全性ƈ非仅仅是在Web.xml 和ejb-jar.xml文g中用合适的声明Q也不是使用J2EE技术,如Java 认证和授权服务(Java Authentication and Authorization ServiceQJAASQ。而是l过深思熟虑后的设计,且实C个支持它的架构?/P> <P>W?课:(x)国际化(I18NQ不再是U怸谈兵 <BR>  当今世界的事实是许多p非母语的Z访问?zhn)的公共Web应用E序。随着?sh)子政务的实行,׃它允思h们(某个国家的居民)(j)在线与政府机构交互,所以这一点特别真实。这L(fng)例子包括换发驄或者R辆登记证。许多第一语言不是p的h们很可能访问这L(fng)应用E序。国际化Q即Q“i18n”,因ؓ(f)在“internationalization”这个单词中Q字母i和字母n之间一共有18个字母)(j)使得(zhn)的应用E序能够支持多种语言?BR>  昄Q如果?zhn)的JSP 面中有编码的文本Q或者?zhn)的Java代码q回编码的错误消息Q那么?zhn)要花费很多时间开发此Web应用E序的西班牙语版本。然而,在Web应用E序中,Z(jin)支持多种语言Q文本不是惟一必须“具体化”的部分。因多图像中嵌有文字Q所以图形和囑փ也应该是可配|的。在极端的情况下Q图像(或者颜Ԍ(j)在不同的文化背景中可能有完全不同的意思。类似地QQ何格式化数字和日期的Java代码也必L地化。但问题是:(x)(zhn)的面布局可能也需要更攏V?BR>  例如Q如果?zhn)使用HTML表格来格式化和显C单选项、应用程序题头或注脚Q则(zhn)可能必Mؓ(f)每一U支持的语言更改每一栏的最宽度和表格其他可能的方面。ؓ(f)?jin)适应不同的字体和颜色Q?zhn)可能必须为每一U语a使用单独的样式表?BR>  昄Q现在创Z个国际化的Web应用E序面(f)的是架构挑战而不是应用程序方面的挑战。一个架构良好的Web应用E序意味着(zhn)的JSP面和所有与业务相关的(应用E序Ҏ(gu)的)(j)Java代码都不知不觉地选择?jin)本地化。要C的教训是Q不要因为Java、J2EE支持国际化而不考虑国际化。?zhn)必须从第一天vp住设计具有国际化的解x案?/P> <P>W?课:(x)在MVC表示中避免共同的错误 <BR>  J2EE开发已l够成熟,在表C层Q大多数目使用MVC架构的某些Ş式,例如Struts。在q样的项目中Q我常见到的现象是对MVC模式的误用。下面是几个CZ?BR>  常见的误用是在模型层Q例如,在Struts的Action Bean中)(j)实现?jin)所有的业务逻辑。不要忘?jin),表示层的模型层仍然是表示层的一部分。用该模型层的正确Ҏ(gu)是调用适当的业务层服务Q或对象Qƈ结果发送到视图层(view layerQ。用设计模式术语来说QMVC表示层的模型应该作ؓ(f)业务层的外观QF(tun)a?adeQ来实现。更好的Ҏ(gu)是,使用核心(j)J2EE模式QCore J2EE PatternsQ中到的Business Delegate模式。这D自书中摘录的内容精彩地概述?jin)将?zhn)的模型作ؓ(f)Business Delegate来实现的要点和优点:(x)<BR>  Business Delegate起到客户端业务抽象化的作用。它抽象化,q而隐藏业务服务的实现。用Business DelegateQ可以降低表C层客户端和pȝ的业务服?之间的耦合E度。根据实现策略不同,Business Delegate可以在业务服务API的实CQ保护客L(fng)不受可能的变动性媄(jing)响。这P在业务服务API或其底层实现变化Ӟ可以潜在地减必M改表C层客户端代码的ơ数?BR>  另一个常见的错误是在模型层中攄许多表示cd的逻辑。例如,如果JSP面需要以指定方式格式化的日期或者以指定方式排序的数据,某些人可能将该逻辑攄在模型层Q对该逻辑来说Q这是错误的地方。实际上Q它应该在JSP面使用的一lhelpercM。当业务层返回数据时QAction Bean应该数据{发给视图层。这P无需创徏模型和视图之间多余的耦合Q就能够灉|支持多个视图层(JSP、Velocity、XML{)(j)。也使视图能够确定向用户昄数据的最x式?BR>  最后,我见q的大多数MVC应用E序都有未充分应用的控制器。例如,l大多数的Struts应用E序创Z个基本的Actionc,q完成所有与安全相关的功能。其他所有的Action Bean都是此基cȝzcR这U功能应该是控制器的一部分Q因为如果没有满_全条Ӟ则首先调用不应该到达Action BeanQ即Q模型)(j)。记住,一个设计良好的MVC架构的最强大功能之一是存在一个健壮的、可扩展的控制器。?zhn)应该利用该能力以加强自己的优ѝ?/P> <P>W?课:(x)不要被JOPO束缚(x)住手?BR>  我曾目睹许多目Z(jin)使用Enterprise JavaBean而用Enterprise JavaBean。因为EJBgl项目带来优感和妄自尊大的表现Q所以有时它是显L(fng)要素Qcoolness factorQ。而其他时候,它会(x)使J2EE和EJB引vh。记住,J2EE和EJB不是同意词。EJB只是J2EE 的一部分QJ2EE 是包含JSP、servlet、Java 消息服务QJMSQ、Java数据库连接(JDBCQ、JAAS?Java理扩展QJMXQ和EJB在内的一pd技术,同样也是有关如何共同使用q些技术徏立解x案的一l指导原则和模式?BR>  如果在不需要用EJB的情况下使用EJBQ它们可能会(x)影响E序的性能。与老的Web服务器相比,EJB一般对应用服务器有更多的需求。EJB提供的所有增值服务一般需要消耗更大的内存和更多的CPU旉。许多应用程序不需要这些服务,因此应用服务器要与应用程序争源?BR>  在某些情况下Q不必要C用EJB可能使应用程序崩溃。例如,最q我遇到?jin)一个在开源应用服务器上开发的应用E序。业务逻辑装在一pd有状态会(x)话beanQEJBQ中。开发h员ؓ(f)?jin)在应用服务器中完全用q些bean的“钝化”费?jin)很大的劌Ӏ客L(fng)要求应用E序部v在某一商用应用服务器上Q而该服务器是客户端技术栈的一部分。该应用服务器却不允许关闭“钝化”功能。事实上Q客L(fng)不想改变与其合作的应用服务器的设M|。结果,开发商到?jin)很大的ȝ?ch)。(gQ有的事情是开发商自己都不能给Zؓ(f)什么将代码用EJBQ而且q是有状态会(x)话beanQ实现的好理由。不仅仅是开发商?x)遇到性能问题Q他们的E序在客户那里也无法工作?BR>  在Web应用E序中,无格式普通Java 对象QPOJOQ是EJB强有力的竞争者。POJO是轻量的,不像EJB那样负担额外的负担。在我看来,对许多EJB的优点,例如对象入池Q估计过高。POJO是?zhn)的朋友,不要被它束?x)住手脚?/P> <P>W?课:(x)数据讉Kq不能托O/R映射 <BR>  我曾参与q的所有Web应用E序都向用户提供从其他地方存取的数据Qƈ且因此需要一个数据访问层。这q不是说所有的目都需要标识ƈ建立q样一个层Q这仅仅说明q样层的存在不是隐含的就是明的。如果是隐含的数据层Q数据层是业务对象(卻I(x)业务服务Q层的一部分。这适用于小型应用程序,但通常与大一些项目所接受的架构指导原则相抵触?BR>  MQ数据访问层必须满或超Z下四个标准:(x)<BR>  h透明?<BR>  业务对象在不知道数据源实现的具体l节情况下,可以使用数据源。由于实现细节隐藏在数据讉K层的内部Q所以访问是透明的?BR>  易于q移<BR>  数据讉K层应用E序很容易迁Ud其他数据库实现。业务对象不?jin)解底层的数据实玎ͼ所以迁UM仅涉?qing)到修改数据讉K层。进一步地_(d)如果(zhn)正在部|某U工厂策略,(zhn)可以ؓ(f)每个底层的存储实现提供具体的工厂实现。如果是那样的话Q迁Ud不同的存储实现意味着为应用程序提供一个新的工厂实现?BR>  量减少业务对象中代码复杂?<BR>  因ؓ(f)数据讉K层管理着所有的数据讉K复杂性,所以它可以化业务对象和使用数据讉K层的其他数据客户端的代码。数据访问层Q而不是业务对象,含有许多与实现相关的代码Q例如SQL语句Q。这L(fng)开发h员带来了(jin)更高的效率、更好的可维护性、提高了(jin)代码的可L等一pd好处?BR>  把所有的数据讉K集中在单独的层上<BR>  ׃所有的数据讉K操作现在都委托给数据讉K层,所以?zhn)可以这个单独的数据讉K层看做能够将应用E序的其他部分与数据讉K实现怺隔离的层。这U集中化可以使应用程序易于维护和理?BR>  注意Q这些标准都不能明确地调出对O/RQ对象到关系Q映层的需求。O/R映射层一般用O/R映射工具创徏Q它提供对象对关pL据结构的查看和感知(look-and-feelQ。在我看来,在项目中使用O/R映射与用EJBcM。在大多数情况下Qƈ不要求它。对于包含中{规模的联合以及(qing)多对多关pȝ关系型数据库来说QO/R映射?x)变得相当复杂。由于增加O/R 映射解决Ҏ(gu)本n的内在复杂性,例如延迟加蝲Qlazy loadingQ、高速缓冲等Q?zhn)?f)(zhn)的目带来更大的复杂性(和风险)(j)?BR>  Z(jin)q一步支持我的观点,我将指出按照Sun Microsystem所普及(qing)的实体BeanQO/R映射的一U实玎ͼ(j)的许多失败的试Q这是自1.0版以来一直折h的难题。在SUN的防卫措施中Q一些早期的问题是有关EJB规范的开发商实现的。这依次证明?jin)实体Bean规范自n的复杂性。结果,大多数J2EE架构师一般认Z实体Bean中脱d来是一个好L?BR>  大多数应用程序在处理他们的数据时Q只能进行有限次数的查询。在q样的应用程序中Q访问数据的一U有效方法是实现一个数据访问层Q该层实现执行这些查询的一pd服务Q或对象、或APIQ。如上所qͼ在这U情况下Q不需要O/R映射。当(zhn)要求查询灵zL时QO/R映射正合适,但要CQ这U附加的灉|性ƈ不是没有代h(hun)的?BR>  像我承诺的那样Q在本文中,我尽量避免陈腐的最?jng)_c(din)相反,关于J2EE目中每一位架构师必须做出的最重要的决定,我集中讲解了(jin)我的观点。最后,(zhn)应该记住:(x)J2EEq某种具体的技术,也不是强行加入到解决Ҏ(gu)中的一些首字母~写。相反,(zhn)应该在适当的时机,恰当的地方,使用合适的技术,q循J2EE的指导原则和J2EE中所包含的比技术本w重要得多的实践?/P> <P>关于作?BR>Tarak Modi是North HighlandQ一家管理和技术咨询公司)(j)的高U专家。他在COM、MTS、COM+?NET、J2EE以及(qing) CORBA{方面有丰富的专业经验?002q曾与h合作~写Professional Java Web Services QWrox PressQ。作者的个h|站是:(x)<A >http://www.tekNirvana.com</A>?/P><img src ="http://www.aygfsteel.com/Weibo-Forum/aggbug/33393.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/Weibo-Forum/" target="_blank">微薄C֌</a> 2006-03-03 10:49 <a href="http://www.aygfsteel.com/Weibo-Forum/archive/2006/03/03/33393.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <a href="http://www.aygfsteel.com/" title="狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频">狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频</a> </div> </footer> վ֩ģ壺 <a href="http://" target="_blank">찲</a>| <a href="http://" target="_blank">ԭ</a>| <a href="http://" target="_blank">ʲ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">Դ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">«</a>| <a href="http://" target="_blank">˷</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">Դ</a>| <a href="http://" target="_blank">Ѯ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ҳ</a>| <a href="http://" target="_blank">Դ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ߺ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">̨</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ʡ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ɽ</a>| <a href="http://" target="_blank">ʩ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ѽ</a>| <a href="http://" target="_blank">Դ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">཭</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">DZ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>