金奎's profile六度万行PhotosBlogListsMore Tools Help

Blog


    June 19

    我的blog

    我的blog:http://javafan.blog.sohu.com
     
     
    April 24

    Java:一种理念一个技术

    Java:一种理念一个技术。
    学Java 的存在着几种人:
    1、跟着潮流学,有什么新技术都学;
    2、根据需要学,根据老板的业务需要学,往往这种学的快;
    3、根据社会需要形成自己的理念和解决方案,这就是新技术。
     
    现在可以看出来这三类的品次了吧!
    April 18

    也谈谈模式

          Java中的模式很多,新出现的也不少,什么Java设计模式,j2EE设计模式 ... ...
          现在主流的框架模式技术有Struts、Hibernate、EJB、Spring、JSF等,这些框架模式本身是通过XML文件配置的,或者说框架本身的内部通讯是要通过XML的形式来实现。尽管这些框架非常优秀,非常出色和成功。但是我们还是要面对Java程序间复杂的逻辑,要面对Java接口,多态等等
     
          既然XML对于这些框架模式如此重要和关键,对于Web开发那么我们干脆直接让数据和数据库打交道,而我们紧紧通过XML和我们的固定程序支持这种模式:
     
     
                     数据 -------------XML  ||  程序支持 ---------------数据库
                                         ------------------------
                                              新的框架
     
           这样更直接,速度更快,我们使用这种模式去开发的代码量就很少了,提高开发效率。

    Ioc模式(又称DI:Dependency Injection)(转载)

    Ioc模式(又称DI:Dependency Injection)

    板桥里人 http://www.jdon.com 2004/01/31

    朱批:文章前半部分讲述概念很不错,后半部分觉得含糊了!

      分离关注( Separation of Concerns : SOC)是Ioc模式和AOP产生最原始动力,通过功能分解可得到关注点,这些关注可以是 组件Components, 方面Aspects或服务Services。

      从GoF设计模式中,我们已经习惯一种思维编程方式:Interface Driven Design 接口驱动,接口驱动有很多好处,可以提供不同灵活的子类实现,增加代码稳定和健壮性等等,但是接口一定是需要实现的,也就是如下语句迟早要执行:

      AInterface a = new AInterfaceImp();

      AInterfaceImp是接口AInterface的一个子类,Ioc模式可以延缓接口的实现,根据需要实现,有个比喻:接口如同空的模型套,在必要时,需要向模型套注射石膏,这样才能成为一个模型实体,因此,我们将人为控制接口的实现成为“注射”。

      Ioc英文为 Inversion of Control,即反转模式,这里有著名的好莱坞理论:你呆着别动,到时我会找你。

      其实Ioc模式也是解决调用者和被调用者之间的一种关系,上述AInterface实现语句表明当前是在调用被调用者AInterfaceImp,由于被调用者名称写入了调用者的代码中,这产生了一个接口实现的原罪:彼此联系,调用者和被调用者有紧密联系,在UML中是用依赖 Dependency 表示。

      但是这种依赖在分离关注的思维下是不可忍耐的,必须切割,实现调用者和被调用者解耦,新的Ioc模式 Dependency Injection 模式由此产生了, Dependency Injection模式是依赖注射的意思,也就是将依赖先剥离,然后在适当时候再注射进入。

    Ioc模式(Dependency Injection模式)有三种:

    第一种类型 从JNDI或ServiceManager等获得被调用者,这里类似ServiceLocator模式。 1. EJB/J2EE
    2. Avalon(Apache的一个复杂使用不多的项目)
    第二种类型 使用JavaBeans的setter方法 1. Spring Framework,
    2. WebWork/XWork
    第三种类型 在构造方法中实现依赖 1. PicoContainer,
    2. HiveMind

      有过EJB开发经验的人都知道,每个EJB的调用都需要通过JNDI寻找到工厂性质的Home接口,在我的教程EJB是什么章节中,我也是从依赖和工厂模式角度来阐述EJB的使用。

      在通常传统情况下,为了实现调用者和被调用者解耦,分离,一般是通过工厂模式实现的,下面将通过比较工厂模式和Ioc模式不同,加深理解Ioc模式。

    工厂模式和Ioc

      假设有两个类B 和 C:B作为调用者,C是被调用者,在B代码中存在对C的调用:

    public class B{
       private C comp;
      ......
    }

      实现comp实例有两种途径:单态工厂模式和Ioc。

    工厂模式实现如下:

    public class B{
       private C comp;
      private final static MyFactory myFactory = MyFactory.getInstance();

      public B(){
        this.comp = myFactory.createInstanceOfC();

      }
       public void someMethod(){
        this.comp.sayHello();
      }
      ......
    }

    特点:

    • 每次运行时,MyFactory可根据配置文件XML中定义的C子类实现,通过createInstanceOfC()生成C的具体实例。

    使用Ioc依赖性注射( Dependency Injection )实现Picocontainer如下,B类如同通常POJO类,如下:

    public class B{
       private C comp;
      public B(C comp){
        this.comp = comp;
       }
       public void someMethod(){
        this.comp.sayHello();
       }
      ......
    }

    假设C接口/类有有一个具体实现CImp类。当客户端调用B时,使用下列代码:

    public class client{
       public static void main( String[] args ) {
        DefaultPicoContainer container = new DefaultPicoContainer();
        container.registerComponentImplementation(CImp.class);
        container.registerComponentImplementation(B.class);
        B b = (B) container.getComponentInstance(B.class);
        b.someMethod();
       }
    }

      因此,当客户端调用B时,分别使用工厂模式和Ioc有不同的特点和区别:

      主要区别体现在B类的代码,如果使用Ioc,在B类代码中将不需要嵌入任何工厂模式等的代码,因为这些工厂模式其实还是与C有些间接的联系,这样,使用Ioc彻底解耦了B和C之间的联系。

      使用Ioc带来的代价是:需要在客户端或其它某处进行B和C之间联系的组装。

      所以,Ioc并没有消除B和C之间这样的联系,只是转移了这种联系。
      这种联系转移实际也是一种分离关注,它的影响巨大,它提供了AOP实现的可能。

    Ioc和AOP

      AOP我们已经知道是一种面向切面的编程方式,由于Ioc解放自由了B类,而且可以向B类实现注射C类具体实现,如果把B类想像成运行时的横向动作,无疑注入C类子类就是AOP中的一种Advice,如下图:

      通过下列代码说明如何使用Picocontainer实现AOP,该例程主要实现是记录logger功能,通过Picocontainer可以使用简单一行,使所有的应用类的记录功能激活。

    首先编制一个记录接口:

    public interface Logging {

      public void enableLogging(Log log);

    }

    有一个LogSwitcher类,主要用来激活具体应用中的记录功能:

    import org.apache.commons.logging.Log;
    public class LogSwitcher
    {
      protected Log m_log;
      public void enableLogging(Log log) {
        m_log = log;
        m_log.info("Logging Enabled");
      }
    }

    一般的普通应用JavaBeans都可以继承这个类,假设PicoUserManager是一个用户管理类,代码如下:

    public class PicoUserManager extends LogSwitcher
    {

      ..... //用户管理功能
    }
    public class PicoXXXX1Manager extends LogSwitcher
    {

      ..... //业务功能
    }
    public class PicoXXXX2Manager extends LogSwitcher
    {

      ..... //业务功能
    }

    注意LogSwitcher中Log实例是由外界赋予的,也就是说即将被外界注射进入,下面看看使用Picocontainer是如何注射Log的具体实例的。


    DefaultPicoContainer container = new DefaultPicoContainer();
    container.registerComponentImplementation(PicoUserManager.class);
    container.registerComponentImplementation(PicoXXXX1Manager.class);
    container.registerComponentImplementation(PicoXXXX2Manager.class);
    .....

    Logging logging = (Logging) container.getComponentMulticaster();

    logging.enableLogging(new SimpleLog("pico"));//激活log

      由上代码可见,通过使用简单一行logging.enableLogging()方法使所有的应用类的记录功能激活。这是不是类似AOP的advice实现?

      总之,使用Ioc模式,可以不管将来具体实现,完全在一个抽象层次进行描述和技术架构,因此,Ioc模式可以为容器、框架之类的软件实现提供了具体的实现手段,属于架构技术中一种重要的模式应用。J道的JdonSD框架也使用了Ioc模式。

    参考资料:

    Inversion of Control Containers and the Dependency Injection pattern

    A Brief Introduction to IoC

    Ioc容器的革命性优点

    Java企业系统架构选择考量

    IOC模式的思考和疑问

    ----------------------

    朱批:文章前半部分讲述概念很不错,后半部分觉得含糊了!

    JSF与Struts的异同(转载)

    JSF与Struts的异同

    板桥里人 http://www.jdon.com 2005/09/05

     (转载)

    注:很久就听说JSF的强大,只不过没时间看,今日看了Jdon的文章,感觉不错。

      Struts和JSF/Tapestry都属于表现层框架,这两种分属不同性质的框架,后者是一种事件驱动型的组件模型,而Struts只是单纯的MVC模式框架,老外总是急吼吼说事件驱动型就比MVC模式框架好,何以见得,我们下面进行详细分析比较一下到底是怎么回事?

      首先事件是指从客户端页面(浏览器)由用户操作触发的事件,Struts使用Action来接受浏览器表单提交的事件,这里使用了Command模式,每个继承Action的子类都必须实现一个方法execute。

      在struts中,实际是一个表单Form对应一个Action类(或DispatchAction),换一句话说:在Struts中实际是一个表单只能对应一个事件,struts这种事件方式称为application event,application event和component event相比是一种粗粒度的事件。

      struts重要的表单对象ActionForm是一种对象,它代表了一种应用,这个对象中至少包含几个字段,这些字段是Jsp页面表单中的input字段,因为一个表单对应一个事件,所以,当我们需要将事件粒度细化到表单中这些字段时,也就是说,一个字段对应一个事件时,单纯使用Struts就不太可能,当然通过结合JavaScript也是可以转弯实现的。

      而这种情况使用JSF就可以方便实现,

    <h:inputText id="userId" value="#{login.userId}">
      <f:valueChangeListener type="logindemo.UserLoginChanged" />
    </h:inputText>

      #{login.userId}表示从名为login的JavaBean的getUserId获得的结果,这个功能使用struts也可以实现,name="login" property="userId"

      关键是第二行,这里表示如果userId的值改变并且确定提交后,将触发调用类UserLoginChanged的processValueChanged(...)方法。

      JSF可以为组件提供两种事件:Value Changed和 Action. 前者我们已经在上节见识过用处,后者就相当于struts中表单提交Action机制,它的JSF写法如下:

    <h:commandButton id="login" commandName="login">
      <f:actionListener type=”logindemo.LoginActionListener” />
    </h:commandButton>

      从代码可以看出,这两种事件是通过Listerner这样观察者模式贴在具体组件字段上的,而Struts此类事件是原始的一种表单提交Submit触发机制。如果说前者比较语言化(编程语言习惯做法类似Swing编程);后者是属于WEB化,因为它是来自Html表单,如果你起步是从Perl/PHP开始,反而容易接受Struts这种风格。

    基本配置

      Struts和JSF都是一种框架,JSF必须需要两种包JSF核心包、JSTL包(标签库),此外,JSF还将使用到Apache项目的一些commons包,这些Apache包只要部署在你的服务器中既可。

      JSF包下载地址:http://java.sun.com/j2ee/javaserverfaces/download.html选择其中Reference Implementation。

      JSTL包下载在http://jakarta.apache.org/site/downloads/downloads_taglibs-standard.cgi

      所以,从JSF的驱动包组成看,其开源基因也占据很大的比重,JSF是一个SUN伙伴们工业标准和开源之间的一个混血儿。

      上述两个地址下载的jar合并在一起就是JSF所需要的全部驱动包了。与Struts的驱动包一样,这些驱动包必须位于Web项目的WEB-INF/lib,和Struts一样的是也必须在web.xml中有如下配置:

    <web-app>
      <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
      </servlet>

      <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.faces</url-pattern>
      </servlet-mapping>
    </web-app>

      这里和Struts的web.xml配置何其相似,简直一模一样。

      正如Struts的struts-config.xml一样,JSF也有类似的faces-config.xml配置文件:


    <faces-config>
      <navigation-rule>
        <from-view-id>/index.jsp</from-view-id>
        <navigation-case>
          <from-outcome>login</from-outcome>
          <to-view-id>/welcome.jsp</to-view-id>
        </navigation-case>
      </navigation-rule>

      <managed-bean>
        <managed-bean-name>user</managed-bean-name>
        <managed-bean-class>com.corejsf.UserBean</managed-bean-class>
        <managed-bean-scope>session</managed-bean-scope>
      </managed-bean>
    </faces-config>

     

      在Struts-config.xml中有ActionForm Action以及Jsp之间的流程关系,在faces-config.xml中,也有这样的流程,我们具体解释一下Navigation:

      在index.jsp中有一个事件:

    <h:commandButton label="Login" action="login" />

      action的值必须匹配form-outcome值,上述Navigation配置表示:如果在index.jsp中有一个login事件,那么事件触发后下一个页面将是welcome.jsp

      JSF有一个独立的事件发生和页面导航的流程安排,这个思路比struts要非常清晰。

      managed-bean类似Struts的ActionForm,正如可以在struts-config.xml中定义ActionForm的scope一样,这里也定义了managed-bean的scope为session。

      但是如果你只以为JSF的managed-bean就这点功能就错了,JSF融入了新的Ioc模式/依赖性注射等技术。

    Ioc模式

      对于Userbean这样一个managed-bean,其代码如下:

    public class UserBean {
      private String name;
      private String password;

      // PROPERTY: name
      public String getName() { return name; }
      public void setName(String newValue) { name = newValue; }

      // PROPERTY: password
      public String getPassword() { return password; }
      public void setPassword(String newValue) { password = newValue; }
    }

    <managed-bean>
      <managed-bean-name>user</managed-bean-name>
      <managed-bean-class>com.corejsf.UserBean</managed-bean-class>
      <managed-bean-scope>session</managed-bean-scope>

      <managed-property>
        <property-name>name</property-name>
        <value>me</value>
      </managed-property>

      <managed-property>
        <property-name>password</property-name>
        <value>secret</value>
      </managed-property>
    </managed-bean>

      faces-config.xml这段配置其实是将"me"赋值给name,将secret赋值给password,这是采取Ioc模式中的Setter注射方式

    Backing Beans

      对于一个web form,我们可以使用一个bean包含其涉及的所有组件,这个bean就称为Backing Bean, Backing Bean的优点是:一个单个类可以封装相关一系列功能的数据和逻辑。

      说白了,就是一个Javabean里包含其他Javabean,互相调用,属于Facade模式或Adapter模式。


      对于一个Backing Beans来说,其中包含了几个managed-bean,managed-bean一定是有scope的,那么这其中的几个managed-beans如何配置它们的scope呢?

    <managed-bean>
      ...
      <managed-property>
        <property-name>visit</property-name>
        <value>#{sessionScope.visit}</value>
      </managed-property>

      这里配置了一个Backing Beans中有一个setVisit方法,将这个visit赋值为session中的visit,这样以后在程序中我们只管访问visit对象,从中获取我们希望的数据(如用户登陆注册信息),而visit是保存在session还是application或request只需要配置既可。

    UI界面

      JSF和Struts一样,除了JavaBeans类之外,还有页面表现元素,都是是使用标签完成的,Struts也提供了struts-faces.tld标签库向JSF过渡。

      使用Struts标签库编程复杂页面时,一个最大问题是会大量使用logic标签,这个logic如同if语句,一旦写起来,搞的JSP页面象俄罗斯方块一样,但是使用JSF标签就简洁优美:

    <jia:navigatorItem name="inbox" label="InBox"
      icon="/images/inbox.gif"
      action="inbox"
      disabled="#{!authenticationBean.inboxAuthorized}"/>

      如果authenticationBean中inboxAuthorized返回是假,那么这一行标签就不用显示,多干净利索!

      先写到这里,我会继续对JSF深入比较下去,如果研究过Jdon框架的人,可能会发现,Jdon框架的jdonframework.xml中service配置和managed-bean一样都使用了依赖注射,看来对Javabean的依赖注射已经迅速地成为一种新技术象征,如果你还不了解Ioc模式,赶紧补课。

    附Jsf核心教程一个JSF案例:login.rar

    相关讨论:

    表现层框架Struts/Tapestry/JSF架构比较

    讨论

     

    My Java Way

                                                      
                                         Java
                                           |
                                           |
                     ------------------------------------------------
                     ||                   ||                     ||
               
                  J2ME                J2SE                J2EE
                      |                    |                       |
             3G(有发展前途)    坚持学习                 |
                                                                   |
                                       ----------------------------------------------------------------------------------
                                       |       |          |            |             |          |             |       |
                                     Jsp   Servlet  Struts   Hibernate   Spring    EJB3.0     JSF   ......
                                                                                      |          |             |
                                                                                   学习中   学习中     学习中

    最近爱看新闻了

    最近特别爱看新闻
    一打开电脑就想看看"胡布会谈"、两岸最新进展
    还有军事报道,昨天在Sohu的军事频道看的最过瘾
     
    比较关注的还有李敖大哥的“李敖有话说”
    真不赖

    跑、飞、走

    跑吧!
    飞吧!
    走吧!
    留吧!
    -------------------------
    怕什么哪!
    各有道理!
    April 09

    明确要做什么

          昨天去达内听了个免费讲座,感触颇深。
          当我问及设计模式和JDK5.0的细节问题时候,他总是提及一句话:你要做什么,然后才会去想如何去做。听起来这话没什么意思,不过我们常常陷入细节,不能自拔。这时候,这句话就非常有用了。
    April 07

    学会放下

           学会放下。这是去年感受最深的四个字。最初听到这四个字是余世维的讲座上说的一个小故事:余的女儿到一寺院参加一个活动,看到一老和尚端着碗对着一只狗叫:“放下,放下... ...”。这老和尚给狗取这个名字是提醒自己:放下一切。今天晚上睡下第二天都不知道能不能起来,所以放下烦恼和忧郁。
          正确对待烦恼的最好方法就是放下。在校的时候,在不干学生会主席的当天晚上,虽然表面上很豁达,无所谓的样子,晚上回去还是有点别扭,总之不爽。晚上睡觉前告诉自己:“放下,放下,放下昨天的一切,明天开始好好补补专业课,毕竟将来要靠这吃饭”,自第二天起就再也没想过这事,既然已经放下就不应再捡起无谓的烦恼。
           放下烦恼,享受生活的乐趣。
    March 19

    第一次组织参加天津UG

      去年就和家立计划着06年的第一个UG,昨天终于实现了,心情^_^.
          昨天和bea的UG负责人舞剑MM一块坐车到津,第一次来到天津,一路听司机师傅讲解天津历史,感受到天津的古朴。
      这次终于见到了咚咚,还以为他肯定是胖胖的,今日一见和Me一样,精瘦。我们俩人到了一起,一见如故,谈了很多。跟咚咚在一起,觉得很随和,随意,谈什么都行。
      这次还见到王宇大哥,这可是牛人,以前就常听老李提起,今日一见,名不虚传。王宇大哥项目经验非常丰富,技术精良,这牛人可是每次UG必去。他说的一些项目经验非常受用,实际。最为一个程序员最可贵的良好的心态在他身上都可以找到。有一个良好的心态加上积极乐观的态度,是程序员基本素质,也是最可贵的地方。
      没想到这次UG去了这么多人,签到时候一拨一拨的,让我们应接不暇。最后会场坐满没位子了,加了一排椅子还是不够,没办法会场椅子放不下了,只能站着了。气氛挺活跃的,有个红工厂的小伙子至少提问了六七次,这家伙问题真不少,呵呵!
      
      这次活动学到了不少,交了几个朋友,心里比较舒畅。回北京都10点了,到家到头就睡,香!
    March 02

    调整心里状态

         心情糟透了,做什么事都没意思。
         天天好心情,天天好天气!
         今天早晨刚起来,金黄的阳光洒满了整个被子,顿觉得心情舒畅。天天早上听张明明唱<<两只蝴蝶>>,今天没听见他唱,^_^,轮到*家上场了。一曲下来不觉过瘾,又唱起了弹棉花 .^_^.  
        
          总觉得自己的状态早已经调整好了,现在才发现是在骗自己玩。调整自己的心情就像改变天气那么难,更别说掌控自己的状态了。我们不要完全期望掌控我们自己的心情,但是可以引导心情,做一下高兴的事,比如自己爱唱歌就唱歌,自己喜欢打球就常打球。另外,人生不如意事十有八九,所以我们要常想一二。让快乐主导我们,带着这个心情去学习,去工作,有什么做不好的哪!
          今天上午,一到公司就开始做EGT网站的原型,一上午,做了个主页面。这是有史以来做的最令自己满意的一个主页面。从布局到主色调搭配,堪称^_^,吹牛了。后来得到杨国武和代立明的强烈^_^肯定。希望能按照我的这个思路继续走下去,虽然又提出了新的要求。
          下午,终于把win2003的群集搞定了,^_^。 然后把没个关键的步骤的画面住了下来,不过还没来得及详细写注释,有时间再说吧^_^.明天要实际测试一下集群的威力,这就准备测试的材料和工具。
     
          今天就干了这两件事,还不错。 天天好心情,天天好天气!
          明天还是金黄艳阳天!!
        
    February 23

    2006.2.23 对测试问题想法

    今天测试了一天发现一个问题:测试不规范。

    首先,测试计划要有计划。测试计划是很重要的,它记录了测试人员的测试方法方式,具有可追踪性,计划性。最大的好处事是使测试不再盲目,像无头苍蝇,撞到什么是什么。这样也提高了工作效率。

    测试计划应该包含以下信息:测试编号、用户身份、测试方案、测试结果(有BUG,符合预期效果)、严重程度(如果有BUG)、测试人。

        再者,测试要可追踪。对于测试人员发现的问题提交给开发人员,开发人员对问题的处理和处理结果。这样再发现同样的问题就可以查找测试结果处理报告马上解决。这样,新手或者新参与到项目的人员遇到这样的问题有据可查,提高了工作效率。

    测试结果处理报告应包含以下内容:测试编号、用户身份、测试方案、测试结果(有BUG,符合预期效果)、严重程度(如果有BUG)、测试人、调试人、调试时间、是否调试、修改的文件及行数、问题总结。

     

    如果测试的计划性和可追踪性做好了,结果是:我们不再用加班来弥补我们不规范浪费的时间了。