<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆 - 81  文章 - 1033  trackbacks - 0
    <2007年1月>
    31123456
    78910111213
    14151617181920
    21222324252627
    28293031123
    45678910

    在浮躁的年代里,我們進取心太切,患得患失;虛榮心太強,戰戰兢兢。一心爭強好勝,惟恐榜上無名。
    I think I can fly , and flying like a bird !
    程序員一名,已售出,缺貨中!

    我的郵件聯系方式

    用且僅用于MSN

    博客點擊率
    free web counter
    free web counter

    常用鏈接

    留言簿(36)

    隨筆檔案

    搜索

    •  

    積分與排名

    • 積分 - 186960
    • 排名 - 309

    最新評論

    閱讀排行榜

    評論排行榜

    摘自 http://www.crackj2ee.com/Article/ShowArticle.asp?ArticleID=462

    初學強烈推薦

    Spring是一個非常優秀的輕量級框架,通過Spring的IoC容器,我們的關注點便放到了需要實現的業務邏輯上。對AOP的支持則能讓我們動態增強業務方法。編寫普通的業務邏輯Bean是非常容易而且易于測試的,因為它能脫離J2EE容器(如Servlet,JSP環境)單獨進行單元測試。最后的一步便是在Spring框架中將這些業務Bean以XML配置文件的方式組織起來,它們就按照我們預定的目標正常工作了!非常容易!

    本文將給出一個基本的Spring入門示例,并演示如何使用Spring的AOP將復雜的業務邏輯分離到每個方面中。

    1.開發環境配置
    2.編寫Bean接口及其實現
    3.在Spring中配置Bean并獲得Bean的實例
    4.編寫Advisor以增強ServiceBean
    5.總結

    1.開發環境配置

    首先,需要正確配置Java環境。推薦安裝JDK1.4.2,并正確配置環境變量:

    JAVA_HOME=<JDK安裝目錄>
    CLASSPATH=.
    Path=%JAVA_HOME%\bin;……

    我們將使用免費的Eclipse 3.1作為IDE。新建一個Java Project,將Spring的發布包spring.jar以及commons-logging-1.0.4.jar復制到Project目錄下,并在Project > Properties中配置好Java Build Path:

    2.編寫Bean接口及其實現

    我們實現一個管理用戶的業務Bean。首先定義一個ServiceBean接口,聲明一些業務方法:

    				/**
    ?* Copyright_2006, Liao Xuefeng
    ?* Created on 2006-3-9
    ?* For more information, please visit:
    http://www.crackj2ee.com
    ?*/
    package com.crackj2ee.example.spring;
    				/**
    ?* Interface of service facade.
    ?*
    ?* @author Xuefeng
    ?*/
    public interface ServiceBean {
    ??? void addUser(String username, String password);
    ??? void deleteUser(String username);
    ??? boolean findUser(String username);
    ??? String getPassword(String username);
    }

    然后在MyServiceBean中實現接口:

    				/**
    ?* Copyright_2006, Liao Xuefeng
    ?* Created on 2006-3-9
    ?*
    ?* For more information, please visit:
    http://www.crackj2ee.com
    ?*/
    package com.crackj2ee.example.spring;
    				import java.util.*;
    		
    				public class MyServiceBean implements ServiceBean {
    		
    				??? private String dir;
    ??? private Map map = new HashMap();
    				??? public void setUserDir(String dir) {
    ??????? this.dir = dir;
    ??????? System.out.println("Set user dir to: " + dir);
    ??? }
    				??? public void addUser(String username, String password) {
    ??????? if(!map.containsKey(username))
    ??????????? map.put(username, password);
    ??????? else
    ??????????? throw new RuntimeException("User already exist.");
    ??? }
    				??? public void deleteUser(String username) {
    ??????? if(map.remove(username)==null)
    ??????????? throw new RuntimeException("User not exist.");
    ??? }
    				??? public boolean findUser(String username) {
    ??????? return map.containsKey(username);
    ??? }
    				??? public String getPassword(String username) {
    ??????? return (String)map.get(username);
    ??? }
    }

    為了簡化邏輯,我們使用一個Map保存用戶名和口令。

    現在,我們已經有了一個業務Bean。要測試它非常容易,因為到目前為止,我們還沒有涉及到Spring容器,也沒有涉及到任何Web容器(假定這是一個Web應用程序關于用戶管理的業務Bean)。完全可以直接進行Unit測試,或者,簡單地寫個main方法測試:

    				/**
    ?* Copyright_2006, Liao Xuefeng
    ?* Created on 2006-3-9
    ?* For more information, please visit:
    http://www.crackj2ee.com
    ?*/
    package com.crackj2ee.example.spring;
    				public class Main {
    		
    				??? public static void main(String[] args) throws Exception {
    ??????? ServiceBean service = new MyServiceBean();
    ??????? service.addUser("bill", "hello");
    ??????? service.addUser("tom", "goodbye");
    ??????? service.addUser("tracy", "morning");
    ??????? System.out.println("tom's password is: " + service.getPassword("tom"));
    ??????? if(service.findUser("tom")) {
    ??????????? service.deleteUser("tom");
    ??????? }
    ??? }
    }

    執行結果:

    3.在Spring中配置Bean并獲得Bean的實例

    我們已經在一個main方法中實現了業務,不過,將對象的生命周期交給容器管理是更好的辦法,我們就不必為初始化對象和銷毀對象進行硬編碼,從而獲得更大的靈活性和可測試性。

    想要把ServiceBean交給Spring來管理,我們需要一個XML配置文件。新建一個beans.xml,放到src目錄下,確保在classpath中能找到此配置文件,輸入以下內容:

    				<?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
    "
    http://www.springframework.org/dtd/spring-beans.dtd ">
    <beans>
    ??? <bean id="service" class="com.crackj2ee.example.spring.MyServiceBean" />
    </beans>

    以上XML聲明了一個id為service的Bean,默認地,Spring為每個聲明的Bean僅創建一個實例,并通過id來引用這個Bean。下面,我們修改main方法,讓Spring來管理業務Bean:

    				/**
    ?* Copyright_2006, Liao Xuefeng
    ?* Created on 2006-3-9
    ?* For more information, please visit:
    http://www.crackj2ee.com
    ?*/
    package com.crackj2ee.example.spring;
    				import org.springframework.beans.factory.xml.XmlBeanFactory;
    import org.springframework.core.io.ClassPathResource;
    				public class Main {
    		
    				??? public static void main(String[] args) throws Exception {
    ??????? // init factory:
    ??????? XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("beans.xml"));
    ??????? // use service bean:
    ??????? ServiceBean service = (ServiceBean)factory.getBean("service");
    ??????? service.addUser("bill", "hello");
    ??????? service.addUser("tom", "goodbye");
    ??????? service.addUser("tracy", "morning");
    ??????? System.out.println("tom's password is \"" + service.getPassword("tom") + "\"");
    ??????? if(service.findUser("tom")) {
    ??????????? service.deleteUser("tom");
    ??????? }
    ??????? // close factory:
    ??????? factory.destroySingletons();
    ??? }
    }

    執行結果:
    ?

    由于我們要通過main方法啟動Spring環境,因此,首先需要初始化一個BeanFactory。紅色部分是初始化Spring的BeanFactory的典型代碼,只需要保證beans.xml文件位于classpath中。

    然后,在BeanFactory中通過id查找,即可獲得相應的Bean的實例,并將其適當轉型為合適的接口。

    接著,實現一系列業務操作,在應用程序結束前,讓Spring銷毀所有的Bean實例。

    對比上一個版本的Main,可以看出,最大的變化是不需要自己管理Bean的生命周期。另一個好處是在不更改實現類的前提下,動態地為應用程序增加功能。

    4.編寫Advisor以增強ServiceBean

    所謂AOP即是將分散在各個方法處的公共代碼提取到一處,并通過類似攔截器的機制實現代碼的動態織入。可以簡單地想象成,在某個方法的調用前、返回前、調用后和拋出異常時,動態插入自己的代碼。在弄清楚Pointcut、Advice之類的術語前,不如編寫一個最簡單的AOP應用來體驗一下。

    考慮一下通常的Web應用程序都會有日志記錄,我們來編寫一個LogAdvisor,對每個業務方法調用前都作一個記錄:

    				/**
    ?* Copyright_2006, Liao Xuefeng
    ?* Created on 2006-3-9
    ?* For more information, please visit:
    http://www.crackj2ee.com
    ?*/
    package com.crackj2ee.example.spring;
    				import java.lang.reflect.Method;
    import org.springframework.aop.MethodBeforeAdvice;
    				public class LogAdvisor implements MethodBeforeAdvice {
    ??? public void before(Method m, Object[] args, Object target) throws Throwable {
    ??????? System.out.println("[Log] " + target.getClass().getName() + "." + m.getName() + "()");
    ??? }
    }

    然后,修改beans.xml:

    				<?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
    "
    http://www.springframework.org/dtd/spring-beans.dtd ">
    				<beans>
    ??? <bean id="serviceTarget" class="com.crackj2ee.example.spring.MyServiceBean" />
    				??? <bean id="logAdvisor" class="com.crackj2ee.example.spring.LogAdvisor" />
    		
    				??? <bean id="service" class="org.springframework.aop.framework.ProxyFactoryBean">
    ??????? <property name="proxyInterfaces"><value>com.crackj2ee.example.spring.ServiceBean</value></property>
    ??????? <property name="target"><ref local="serviceTarget"/></property>
    ??????? <property name="interceptorNames">
    ??????????? <list>
    ??????????????? <value>logAdvisor</value>
    ??????????? </list>
    ??????? </property>
    ??? </bean>
    </beans>

    注意觀察修改后的配置文件,我們使用了一個ProxyFactoryBean作為service來與客戶端打交道,而真正的業務Bean即MyServiceBean被聲明為serviceTarget并作為參數對象傳遞給ProxyFactoryBean,proxyInterfaces指定了返回的接口類型。對于客戶端而言,將感覺不出任何變化,但卻動態加入了LogAdvisor,關系如下:
    ?

    運行結果如下,可以很容易看到調用了哪些方法:
    ?

    要截獲指定的某些方法也是可以的。下面的例子將修改getPassword()方法的返回值:

    				/**
    ?* Copyright_2006, Liao Xuefeng
    ?* Created on 2006-3-9
    ?* For more information, please visit:
    http://www.crackj2ee.com
    ?*/
    package com.crackj2ee.example.spring;
    				import org.aopalliance.intercept.MethodInterceptor;
    import org.aopalliance.intercept.MethodInvocation;
    				public class PasswordAdvisor implements MethodInterceptor {
    ??? public Object invoke(MethodInvocation invocation) throws Throwable {
    ??????? Object ret = invocation.proceed();
    ??????? if(ret==null)
    ??????????? return null;
    ??????? String password = (String)ret;
    ??????? StringBuffer encrypt = new StringBuffer(password.length());
    ??????? for(int i=0; i<password.length(); i++)
    ??????????? encrypt.append('*');
    ??????? return encrypt.toString();
    ??? }
    }

    這個PasswordAdvisor將截獲ServiceBean的getPassword()方法的返回值,并將其改為"***"。繼續修改beans.xml:

    				<?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
    "
    http://www.springframework.org/dtd/spring-beans.dtd ">
    <beans>
    ??? <bean id="serviceTarget" class="com.crackj2ee.example.spring.MyServiceBean" />
    				??? <bean id="logAdvisor" class="com.crackj2ee.example.spring.LogAdvisor" />
    		
    				??? <bean id="passwordAdvisorTarget" class="com.crackj2ee.example.spring.PasswordAdvisor" />
    		
    				??? <bean id="passwordAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
    ??????? <property name="advice">
    ??????????? <ref local="passwordAdvisorTarget"/>
    ??????? </property>
    ??????? <property name="patterns">
    ??????????? <list>
    ??????????????? <value>.*getPassword</value>
    ??????????? </list>
    ??????? </property>
    ??? </bean>
    				??? <bean id="service" class="org.springframework.aop.framework.ProxyFactoryBean">
    ??????? <property name="proxyInterfaces"><value>com.crackj2ee.example.spring.ServiceBean</value></property>
    ??????? <property name="target"><ref local="serviceTarget"/></property>
    ??????? <property name="interceptorNames">
    ??????????? <list>
    ??????????????? <value>logAdvisor</value>
    ??????????????? <value>passwordAdvisor</value>
    ??????????? </list>
    ??????? </property>
    ??? </bean>
    </beans>

    利用Spring提供的一個RegexMethodPointcutAdvisor可以非常容易地指定要截獲的方法。運行結果如下,可以看到返回結果變為"******":
    ?

    還需要繼續增強ServiceBean?我們編寫一個ExceptionAdvisor,在業務方法拋出異常時能做一些處理:

    				/**
    ?* Copyright_2006, Liao Xuefeng
    ?* Created on 2006-3-9
    ?* For more information, please visit:
    http://www.crackj2ee.com
    ?*/
    package com.crackj2ee.example.spring;
    				import org.springframework.aop.ThrowsAdvice;
    		
    				public class ExceptionAdvisor implements ThrowsAdvice {
    ??? public void afterThrowing(RuntimeException re) throws Throwable {
    ??????? System.out.println("[Exception] " + re.getMessage());
    ??? }
    }

    將此Advice添加到beans.xml中,然后在業務Bean中刪除一個不存在的用戶,故意拋出異常:

    				service.deleteUser("not-exist");
    		

    再次運行,注意到ExceptionAdvisor記錄下了異常:
    ?

    5.總結

    利用Spring非常強大的IoC容器和AOP功能,我們能實現非常靈活的應用,讓Spring容器管理業務對象的生命周期,利用AOP增強功能,卻不影響業務接口,從而避免更改客戶端代碼。

    為了實現這一目標,必須始終牢記:面向接口編程。而Spring默認的AOP代理也是通過Java的代理接口實現的。雖然Spring也可以用CGLIB實現對普通類的代理,但是,業務對象只要沒有接口,就會變得難以擴展、維護和測試。

    歡迎來信與作者交流:asklxf@163.com

    可以從此處下載完整的Eclipse工程:

    springbasic.rar

    posted on 2007-01-11 22:44 cresposhi 閱讀(1441) 評論(5)  編輯  收藏

    FeedBack:
    # re: Spring入門 (spring初學非常好的文章) 【轉載】 2007-02-02 12:35 小祝
    終于找到個沙發了,哈哈.小梅,怎么這個你沒搶啊,留給我的呀.
    圖片上有錯誤,記得改下,哈哈.  回復  更多評論
      
    # re: Spring入門 (spring初學非常好的文章) 【轉載】 2007-02-02 14:21 梅穎
    喲,真的列,呵呵,枉費我這個超級粉絲的稱號了  回復  更多評論
      
    # re: Spring入門 (spring初學非常好的文章) 【轉載】 2007-02-02 14:36 kirari_wxy
    哎 現在到處都是反射機制了  回復  更多評論
      
    # re: Spring入門 (spring初學非常好的文章) 【轉載】 2007-02-02 20:46 施偉
    反射現在幾乎成了JAVA核心技術中運用最為廣泛的技術了。。。沒有哪個框架不用它,一般編程過程中也很好用。主要是更利于設計中的抽象  回復  更多評論
      
    # re: Spring入門 (spring初學非常好的文章) 【轉載】 2007-02-02 22:20 梅穎
    嗯。。。真有道理。。。哈哈  回復  更多評論
      

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


    網站導航:
     
    主站蜘蛛池模板: 亚洲成av人片在线天堂无| fc2免费人成为视频| 免费一级特黄特色大片在线| 二级毛片免费观看全程| 亚洲∧v久久久无码精品| 最近免费中文字幕大全| 野花香高清视频在线观看免费 | 亚洲综合色区中文字幕| 亚洲成年人啊啊aa在线观看| 香港a毛片免费观看| 亚洲国产无线乱码在线观看| 亚洲精品夜夜夜妓女网| 成人毛片免费观看视频在线| 三级网站在线免费观看| 亚洲欧美日韩国产精品一区| 亚洲成AV人片一区二区| 国产免费一区二区三区VR| 国产精品网站在线观看免费传媒| 亚洲精品精华液一区二区| 亚洲成人在线电影| 国产a不卡片精品免费观看| 亚洲精品视频在线观看免费| 免费看一级高潮毛片| 国产精品亚洲综合五月天| 亚洲午夜久久久久妓女影院| 全免费a级毛片免费看不卡| 99在线免费观看视频| 日亚毛片免费乱码不卡一区 | 日韩毛片一区视频免费| 亚洲午夜精品在线| 亚洲AV永久无码精品成人| 亚洲AV成人潮喷综合网| 嫩草影院在线免费观看| 中文字幕在线观看免费视频| 国产无遮挡又黄又爽免费网站| 在线观看亚洲网站| 亚洲欧美日韩国产成人| 亚洲欧洲精品一区二区三区| 亚洲AV无码一区二区二三区入口 | 久久乐国产精品亚洲综合| 国产网站在线免费观看|