2008年6月26日
#
c3p0很容易使用的開源專業(yè)級jdbc數(shù)據(jù)庫緩沖池。
它是sourceforge上的一個開源項目,
項目在
http://sourceforge.net/projects/c3p0
他的眾多特性這里就不一一介紹了。
比較爽的一點就是
當(dāng)Connection歸還緩沖池時,c3p0會很小心的關(guān)閉
這條連接打開的Statement和ResultSet,免去了使用時
自己動手小心翼翼的關(guān)閉。
c3p0使用非常簡單,這里給一個例子
package common.db;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import com.mchange.v2.c3p0.DataSources;
public final class ConnectionManager {
?private static ConnectionManager instance;
?
?public ComboPooledDataSource ds;
?private static String c3p0Properties="c3p0.properties";
?
?private ConnectionManager() throws Exception {
??Properties p = new Properties();
??p.load(this.getClass().getResourceAsStream(c3p0Properties));
??ds = new ComboPooledDataSource();
?}
?
?public static final ConnectionManager getInstance() {
??if (instance == null) {
???try {
????instance = new ConnectionManager();
???} catch (Exception e) {
????e.printStackTrace();
???}
??}
??return instance;
?}
?
?public synchronized final Connection getConnection() {
??try {
???return ds.getConnection();
??} catch (SQLException e) {
???e.printStackTrace();
??}
??return null;
?}
?protected void finalize() throws Throwable {
??DataSources.destroy(ds);?//關(guān)閉datasource
??super.finalize();
?}
?
}
然后在ConnectionManager類的目錄下再創(chuàng)建一個配置文件c3p0.properties
內(nèi)容如下:
#db login parameters
driverClass=com.mysql.jdbc.Driver
jdbcUrl=jdbc:mysql://localhost/test?useUnicode=no&characterEncoding=GBK
user=test
password=test
#pool parameters
initialPoolSize=2
maxPoolSize=5
#maxIdleTime=10
#idleConnectionTestPeriod=5
autoCommitOnClose=true
完整的配置文件參數(shù)參看c3p0的文檔
使用connection時很簡單
Connection conn = ConnectionManager.getInstance().getConnection();
...
最后 conn.close() 即可,
如題。研究中...以前沒有注意過。
*匹配除了換行之外的所有字符
合法IP的正則表達式 ((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)
\s匹配任意的空白符、(空格、制表符、換行符、中文全角空格)
\w匹配字母或數(shù)字或下劃線或漢字
表1.常用的元字符代碼 | 說明 |
---|
. | 匹配除換行符以外的任意字符 |
\w | 匹配字母或數(shù)字或下劃線或漢字 |
\s | 匹配任意的空白符 |
\d | 匹配數(shù)字 |
\b | 匹配單詞的開始或結(jié)束 |
^ | 匹配字符串的開始 |
$ | 匹配字符串的結(jié)束 |
表2.常用的限定符代碼/語法 | 說明 |
---|
* | 重復(fù)零次或更多次 |
+ | 重復(fù)一次或更多次 |
? | 重復(fù)零次或一次 |
{n} | 重復(fù)n次 |
{n,} | 重復(fù)n次或更多次 |
{n,m} | 重復(fù)n到m次 |
后向引用
使用小括號指定一個子表達式后,匹配這個子表達式的文本(也就是此分組捕獲的內(nèi)容)可以在表達式或其它程序中作進一步的處理。默認情況下,每個分組會自動擁有一個組號,規(guī)則是:從左向右,以分組的左括號為標(biāo)志,第一個出現(xiàn)的分組的組號為1,第二個為2,以此類推。
后向引用用于重復(fù)搜索前面某個分組匹配的文本。例如,\1代表分組1匹配的文本。難以理解?請看示例:
\b(\w+)\b\s+\1\b可以用來匹配重復(fù)的單詞,像go go, 或者kitty kitty。這個表達式首先是一個單詞,也就是單詞開始處和結(jié)束處之間的多于一個的字母或數(shù)字(\b(\w+)\b),這個單詞會被捕獲到編號為1的分組中,然后是1個或幾個空白符(\s+),最后是分組1中捕獲的內(nèi)容(也就是前面匹配的那個單詞)(\1)。
你也可以自己指定子表達式的組名。要指定一個子表達式的組名,請使用這樣的語法:(?<Word>\w+)(或者把尖括號換成'也行:(?'Word'\w+)),這樣就把\w+的組名指定為Word了。要反向引用這個分組捕獲的內(nèi)容,你可以使用\k<Word>,所以上一個例子也可以寫成這樣:\b(?<Word>\w+)\b\s+\k<Word>\b。
使用小括號的時候,還有很多特定用途的語法。下面列出了最常用的一些:
表4.常用分組語法分類 | 代碼/語法 | 說明 |
---|
捕獲 | (exp) | 匹配exp,并捕獲文本到自動命名的組里 |
---|
(?<name>exp) | 匹配exp,并捕獲文本到名稱為name的組里,也可以寫成(?'name'exp) |
(?:exp) | 匹配exp,不捕獲匹配的文本,也不給此分組分配組號 |
零寬斷言 | (?=exp) | 匹配exp前面的位置 |
---|
(?<=exp) | 匹配exp后面的位置 |
(?!exp) | 匹配后面跟的不是exp的位置 |
(?<!exp) | 匹配前面不是exp的位置 |
注釋 | (?#comment) | 這種類型的分組不對正則表達式的處理產(chǎn)生任何影響,用于提供注釋讓人閱讀 |
---|
表5.懶惰限定符代碼/語法 | 說明 |
---|
*? | 重復(fù)任意次,但盡可能少重復(fù) |
+? | 重復(fù)1次或更多次,但盡可能少重復(fù) |
?? | 重復(fù)0次或1次,但盡可能少重復(fù) |
{n,m}? | 重復(fù)n到m次,但盡可能少重復(fù) |
{n,}? | 重復(fù)n次以上,但盡可能少重復(fù) |
表6.常用的處理選項名稱 | 說明 |
---|
IgnoreCase(忽略大小寫) | 匹配時不區(qū)分大小寫。 |
Multiline(多行模式) | 更改^和$的含義,使它們分別在任意一行的行首和行尾匹配,而不僅僅在整個字符串的開頭和結(jié)尾匹配。(在此模式下,$的精確含意是:匹配\n之前的位置以及字符串結(jié)束前的位置.) |
Singleline(單行模式) | 更改.的含義,使它與每一個字符匹配(包括換行符\n)。 |
IgnorePatternWhitespace(忽略空白) | 忽略表達式中的非轉(zhuǎn)義空白并啟用由#標(biāo)記的注釋。 |
RightToLeft(從右向左查找) | 匹配從右向左而不是從左向右進行。 |
ExplicitCapture(顯式捕獲) | 僅捕獲已被顯式命名的組。 |
ECMAScript(JavaScript兼容模式) | 使表達式的行為與它在JavaScript里的行為一致。 |
表7.尚未詳細討論的語法代碼/語法 | 說明 |
---|
\a | 報警字符(打印它的效果是電腦嘀一聲) |
\b | 通常是單詞分界位置,但如果在字符類里使用代表退格 |
\t | 制表符,Tab |
\r | 回車 |
\v | 豎向制表符 |
\f | 換頁符 |
\n | 換行符 |
\e | Escape |
\0nn | ASCII代碼中八進制代碼為nn的字符 |
\xnn | ASCII代碼中十六進制代碼為nn的字符 |
\unnnn | Unicode代碼中十六進制代碼為nnnn的字符 |
\cN | ASCII控制字符。比如\cC代表Ctrl+C |
\A | 字符串開頭(類似^,但不受處理多行選項的影響) |
\Z | 字符串結(jié)尾或行尾(不受處理多行選項的影響) |
\z | 字符串結(jié)尾(類似$,但不受處理多行選項的影響) |
\G | 當(dāng)前搜索的開頭 |
\p{name} | Unicode中命名為name的字符類,例如\p{IsGreek} |
(?>exp) | 貪婪子表達式 |
(?<x>-<y>exp) | 平衡組 |
(?im-nsx:exp) | 在子表達式exp中改變處理選項 |
(?im-nsx) | 為表達式后面的部分改變處理選項 |
(?(exp)yes|no) | 把exp當(dāng)作零寬正向先行斷言,如果在這個位置能匹配,使用yes作為此組的表達式;否則使用no |
(?(exp)yes) | 同上,只是使用空表達式作為no |
(?(name)yes|no) | 如果命名為name的組捕獲到了內(nèi)容,使用yes作為表達式;否則使用no |
(?(name)yes) | 同上,只是使用空表達式作為no |
Lucene是一個高性能的java全文檢索工具包,它使用的是倒排文件索引結(jié)構(gòu)。該結(jié)構(gòu)及相應(yīng)的生成算法如下:
0)設(shè)有兩篇文章1和2
文章1的內(nèi)容為:Tom?lives?in?Guangzhou,I?live?in?Guangzhou?too.
文章2的內(nèi)容為:He?once?lived?in?Shanghai.
1)由于lucene是基于關(guān)鍵詞索引和查詢的,首先我們要取得這兩篇文章的關(guān)鍵詞,通常我們需要如下處理措施
a.我們現(xiàn)在有的是文章內(nèi)容,即一個字符串,我們先要找出字符串中的所有單詞,即分詞。英文單詞由于用空格分隔,比較好處理。中文單詞間是連在一起的需要特殊的分詞處理。
b.文章中的”in”,?“once”?“too”等詞沒有什么實際意義,中文中的“的”“是”等字通常也無具體含義,這些不代表概念的詞可以過濾掉
c.用戶通常希望查“He”時能把含“he”,“HE”的文章也找出來,所以所有單詞需要統(tǒng)一大小寫。
d.用戶通常希望查“l(fā)ive”時能把含“l(fā)ives”,“l(fā)ived”的文章也找出來,所以需要把“l(fā)ives”,“l(fā)ived”還原成“l(fā)ive”
e.文章中的標(biāo)點符號通常不表示某種概念,也可以過濾掉
在lucene中以上措施由Analyzer類完成
經(jīng)過上面處理后
????文章1的所有關(guān)鍵詞為:[tom]?[live]?[guangzhou]?[i]?[live]?[guangzhou]
????文章2的所有關(guān)鍵詞為:[he]?[live]?[shanghai]
2)?有了關(guān)鍵詞后,我們就可以建立倒排索引了。上面的對應(yīng)關(guān)系是:“文章號”對“文章中所有關(guān)鍵詞”。倒排索引把這個關(guān)系倒過來,變成:“關(guān)鍵詞”對“擁有該關(guān)鍵詞的所有文章號”。文章1,2經(jīng)過倒排后變成
關(guān)鍵詞???文章號
guangzhou??1
he?????????2
i???????????1
live???????1,2
shanghai???2
tom?????????1
通常僅知道關(guān)鍵詞在哪些文章中出現(xiàn)還不夠,我們還需要知道關(guān)鍵詞在文章中出現(xiàn)次數(shù)和出現(xiàn)的位置,通常有兩種位置:a)字符位置,即記錄該詞是文章中第幾個字符(優(yōu)點是關(guān)鍵詞亮顯時定位快);b)關(guān)鍵詞位置,即記錄該詞是文章中第幾個關(guān)鍵詞(優(yōu)點是節(jié)約索引空間、詞組(phase)查詢快),lucene中記錄的就是這種位置。
加上“出現(xiàn)頻率”和“出現(xiàn)位置”信息后,我們的索引結(jié)構(gòu)變?yōu)椋?br />關(guān)鍵詞???文章號[出現(xiàn)頻率]???出現(xiàn)位置
guangzhou?1[2]???????????????3,6
he???????2[1]???????????????1
i?????????1[1]???????????????4
live??????1[2],2[1]???????????2,5,2
shanghai??2[1]???????????????3
tom??????1[1]???????????????1
以live 這行為例我們說明一下該結(jié)構(gòu):live在文章1中出現(xiàn)了2次,文章2中出現(xiàn)了一次,它的出現(xiàn)位置為“2,5,2”這表示什么呢?我們需要結(jié)合文章號和出現(xiàn)頻率來分析,文章1中出現(xiàn)了2次,那么“2,5”就表示live在文章1中出現(xiàn)的兩個位置,文章2中出現(xiàn)了一次,剩下的“2”就表示live是文章2中第 2個關(guān)鍵字。
????
以上就是lucene索引結(jié)構(gòu)中最核心的部分。我們注意到關(guān)鍵字是按字符順序排列的(lucene沒有使用B樹結(jié)構(gòu)),因此lucene可以用二元搜索算法快速定位關(guān)鍵詞。
????
實現(xiàn)時?lucene將上面三列分別作為詞典文件(Term?Dictionary)、頻率文件(frequencies)、位置文件 (positions)保存。其中詞典文件不僅保存有每個關(guān)鍵詞,還保留了指向頻率文件和位置文件的指針,通過指針可以找到該關(guān)鍵字的頻率信息和位置信息。
????Lucene中使用了field的概念,用于表達信息所在位置(如標(biāo)題中,文章中,url中),在建索引中,該field信息也記錄在詞典文件中,每個關(guān)鍵詞都有一個field信息(因為每個關(guān)鍵字一定屬于一個或多個field)。
???? 為了減小索引文件的大小,Lucene對索引還使用了壓縮技術(shù)。首先,對詞典文件中的關(guān)鍵詞進行了壓縮,關(guān)鍵詞壓縮為<前綴長度,后綴>,例如:當(dāng)前詞為“阿拉伯語”,上一個詞為“阿拉伯”,那么“阿拉伯語”壓縮為<3,語>。其次大量用到的是對數(shù)字的壓縮,數(shù)字只保存與上一個值的差值(這樣可以減小數(shù)字的長度,進而減少保存該數(shù)字需要的字節(jié)數(shù))。例如當(dāng)前文章號是16389(不壓縮要用3個字節(jié)保存),上一文章號是16382,壓縮后保存7(只用一個字節(jié))。
????
????下面我們可以通過對該索引的查詢來解釋一下為什么要建立索引。
假設(shè)要查詢單詞?“l(fā)ive”,lucene先對詞典二元查找、找到該詞,通過指向頻率文件的指針讀出所有文章號,然后返回結(jié)果。詞典通常非常小,因而,整個過程的時間是毫秒級的。
而用普通的順序匹配算法,不建索引,而是對所有文章的內(nèi)容進行字符串匹配,這個過程將會相當(dāng)緩慢,當(dāng)文章數(shù)目很大時,時間往往是無法忍受的。
?
一、 寫jsp頁面的時候,在struts2中,用的是s標(biāo)記,先引入標(biāo)記: <%@ taglib prefix="s" uri="/struts-tags"%> 二、 struts2的標(biāo)簽和1是完全不同的。 struts2的標(biāo)簽分為兩大類:非UI標(biāo)志和UI標(biāo)志 struts1 將標(biāo)志庫按功能分成HTML、Tiles、Logic和Bean等幾部分 下面就介紹strut2的具體標(biāo)簽: 1、UI UI標(biāo)志又可以分為表單UI和非表單UI兩部分。表單UI部分基本與Struts 1.x相同,都是對HTML表單元素的包裝。不過,Struts 2.0加了幾個我們經(jīng)常在項目中用到的控件如:datepicker、doubleselect、timepicker、optiontransferselect等。因為這些標(biāo)志很多都經(jīng)常用到,而且參數(shù)也很多,要在一篇文章詳細說明并非易事。 下面主要是ui標(biāo)簽的一些用法 form: <s:form action="exampleSubmit" method="post" enctype="multipart/form-data"> <s:submit /> ??? <s:reset />
</s:form>可以上傳文件的form。 textfield: <s:textfield ??????????? label="姓名:" ??????????? name="name" ??????????? tooltip="Enter your Name here" /> datepicker: <s:datepicker ??????????? tooltip="Select Your Birthday" ??????????? label="生日" ??????????? name="birthday" /> textarea: <s:textarea ??????????? tooltip="Enter your remart" ??????????? label="備注" ??????????? name="remart" ??????????? cols="20" ??????????? rows="3"/> select: <s:select ??????????? tooltip="Choose user_type" ??????????? label="" ??????????? list="#{'free':'免費','vip':'收費'}" value="#{'free':'免費'}"?? ?????????? name="bean.user_type" ??????????? emptyOption="true" ??????????? headerKey="None" ??????????? headerValue="None"/> <s:select ??????????? tooltip="Choose user_type" ??????????? label="" ??????????? list="#{'free':'免費','vip':'收費'}" value="#{'free':'免費'}"?? ?????????? name="bean.user_type" ??????????? emptyOption="true" ??????????? headerKey="None" ??????????? headerValue="None"/> <s:select list="venderList" listKey="id" listValue="name" value="%{profile.companyName}" name="companyName" cssClass="sel_style_w_180"/>?? 挺好用的 checkboxlist: <s:checkboxlist ??????????? tooltip="Choose your Friends" ??????????? label="朋友" ??????????? list="{'Patrick', 'Jason', 'Jay', 'Toby', 'Rene'}" ??????????? name="friends"/> checkbox: ?? <s:checkbox ??????????? tooltip="Confirmed that your are Over 18" ??????????? label="年齡" ??????????? name="legalAge" ??????????? value="18"/> file: ?? <s:file ??????????? tooltip="Upload Your Picture" ??????????? label="Picture" ??????????? name="picture" /> a: <s:a href="getP.jsp">超鏈接提交</s:a> date : <s:date name="ad_end_time" format="yyyy-MM-dd"/>
2、非UI if、elseif和else 描述: 執(zhí)行基本的條件流轉(zhuǎn)。 參數(shù): 名稱必需默認類型描述備注test是Boolean決定標(biāo)志里內(nèi)容是否顯示的表達式else標(biāo)志沒有這個參數(shù)id否Object/String用來標(biāo)識元素的id。在UI和表單中為HTML的id屬性 例子: <%@ page c %> <%@ taglib prefix="s" uri="/struts-tags" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> ??? <head> ??????? <title>Condition Flow</title> ??? </head> ??? <body> ??????? <h3>Condition Flow</h3>???????????? ??????? <!-- ??????????? 這里有點小技巧: ??????????? 本來可以用#parameters.name[0]來獲得,請求中name的值。但是,在我實現(xiàn)include例子時, ??????????? 無論我用param標(biāo)志給name賦任何值,#parameters里面不會含有任何值,所以#parameters.name也為空值。 ???????????? ??????????? 其原因為: ??????????? 當(dāng)使用include標(biāo)志時,被包含的頁面(included)里#parameters拿到的是包含頁面里的請求參數(shù)。 ???????????? ??????????? 因此,這里必須手工調(diào)用request.getParameter("name")。 ??????? --> ??? <s:iterator value="linkList" status="bean"> ?? <tr> ??? <td class="data_tab_tdcl"> ???? <s:property value="#bean.Index+1" />??? </td> ??? <td class="data_tab_tdcl"><s:property value="link_title" /></td> ??? <td class="data_tab_tdcl"><s:property value="link_url" /></td> ??? <td class="data_tab_tdcl"> ??? <s:if test="link_type == 1"> ?????????????????? 文字 ??????????????? </s:if> ??????????????? <s:elseif test="link_type == 2"> ?????????????????? 圖片 ??????????????? </s:elseif> ???????????????? <s:else> ???????????????? ----- ?????????????? </s:else>??? ??? </td>
??? ??? </body> </html> 例1 condition.jsp iterator 描述: 用于遍歷集合(java.util.Collection)或枚舉值(java.util.Iterator)。 參數(shù): 名稱必需默認類型描述status否String如果設(shè)置此參數(shù),一個IteratorStatus的實例將會壓入每個遍歷的堆棧value否Object/String要遍歷的可枚舉的(iteratable)數(shù)據(jù)源,或者將放入新列表(List)的對象id否Object/String用來標(biāo)識元素的id。在UI和表單中為HTML的id屬性 例子: <%@ page c %> <%@ page import="java.util.List" %> <%@ page import="java.util.ArrayList" %> <%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <% ??? List list = new ArrayList(); ??? list.add("Max"); ??? list.add("Scott"); ??? list.add("Jeffry"); ??? list.add("Joe"); ??? list.add("Kelvin"); ??? request.setAttribute("names", list); %> <html> ??? <head> ??????? <title>Iterator</title> ??? </head> ??? <body> ??????? <h3>Names: </h3> ??????? <!-- ??????????? 1、此處的空property元素用于獲得當(dāng)前iterator的值 ??????????? 2、status被設(shè)成stuts,在iterator的里面就可以通過#stuts取得IteratorStatus的對象。IteratorStatus類包含當(dāng)前序號信息,如是否第一個或最后一個,是否為奇數(shù)序號。這些信息在我們做格式化的時候,顯得非常有用。 ??????? --> ??????? <ol> ??????????? <s:iterator value="#request.names" status="stuts">???????????????? ??????????????? <s:if test="#stuts.odd == true"> ??????????????????? <li>White <s:property /></li> ??????????????? </s:if> ??????????????? <s:else> ??????????????????? <li style="background-color:gray"><s:property /></li> ??????????????? </s:else> ??????????? </s:iterator> ??????? </ol> ??? </body> </html>
|
摘要: EJB
方面
?
94
、
EJB2.0
...
閱讀全文
在我裝完Wincvs之后,提示我沒有安裝python,但后來我又裝了python2.4,可Wincvs還是說配置不對.到底要怎么配置python呢?期待著您的回復(fù),謝謝你了!
???
TCL or Python are not available, shell is disabled。 |
有的網(wǎng)友說是版本的問題,我今天安裝時也是一樣,裝了好三四個版本,都一樣,最后在CSDN上找到了答案。
解決辦法:
在admin-〉Preferences->wincvs中有關(guān)于python的設(shè)置, ?
? 其中python是指你的python虛擬機的位置,一般是python2X.dll的位置。在你來說就是python24.dll的位置,一般這個文件會在你的系統(tǒng)文件中找到。 ?
? Tcl則一般會在python文件架的dlls子文件架中找到,一般名稱為tclxx.dll,在你大概就是tcl84.dll。如果是安裝python2.3版本的話,會自動找到,不需要設(shè)置。
設(shè)置好了,WinCVS輸出窗口:
Python 2.5.2 (r252:60911, Feb 21 2008, 13:11:45) [MSC v.1310 32 bit (Intel)] on win32Tk is available, Tk-macros are enabledTCL is available, shell is enabled : help (select and press enter) |
AbstractFactory模式和可擴展性
假如要實現(xiàn)較好的可擴展性,AbstractFactory模式確實是一件利器。如上面所說,假如要創(chuàng)建的Forum接口的不同實現(xiàn),而又不想更改代碼的話,就需要用到抽象工廠了。再Jive中,AuthorizationFactory類是一個抽象類,用來創(chuàng)建Authorization對象。這是一個抽象工廠,可以通過不同的子類來創(chuàng)建不同的Authorization對象。這個工廠的實現(xiàn)方法是:
在AuthorizationFactory中使用一個private static變量factory,用來引用具體的抽象工廠的實例:
private static AuthorizationFactory factory = null;
用一個private static的String,來指明具體的抽象工廠的子類類名:
private static String className ="com.coolservlets.forum.database.DbAuthorizationFactory";
然后是用一個private static的loadAuthorizationFactory方法來給這個factory變量賦值,生成具體的抽象工廠類:
private static void loadAuthorizationFactory() {
if (factory == null) {
synchronized(className) {
if (factory == null) {
String classNameProp = PropertyManager.getProperty(
"AuthorizationFactory.className"
);
if (classNameProp != null) {
className = classNameProp;
}
try {
Class c = Class.forName(className);
factory = (AuthorizationFactory)c.newInstance();
}
catch (Exception e) {
System.err.println("Exception loading class: " + e);
e.printStackTrace();
}
}
}
}
}
在static的getAuthorization方法返回一個Authorization的過程中,先初始化工廠類factory變量,然后用factory的createAuthorization方法來創(chuàng)建:
public static Authorization getAuthorization(String username,
String passWord) throws UnauthorizedException
{
loadAuthorizationFactory();
return factory.createAuthorization(username, password);
}
不同的子類有不同的createAuthorization方法的實現(xiàn)。比如在DbAuthorizationFactory這個AuthorizationFactory的數(shù)據(jù)庫實現(xiàn)子類中,createAuthorization方法是這樣實現(xiàn)的:
public Authorization createAuthorization(String username, String password)
throws UnauthorizedException
{
if (username == null password == null) {
throw new UnauthorizedException();
}
password = StringUtils.hash(password);
int userID = 0;
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
pstmt = con.prepareStatement(AUTHORIZE);
pstmt.setString(1, username);
pstmt.setString(2, password);
ResultSet rs = pstmt.executeQuery();
if (!rs.next()) {
throw new UnauthorizedException();
}
userID = rs.getInt(1);
}
catch( SQLException sqle ) {
System.err.println("Exception in DbAuthorizationFactory:" + sqle);
sqle.printStackTrace();
throw new UnauthorizedException();
}
finally {
try { pstmt.close(); }
catch (Exception e) { e.printStackTrace(); }
try { con.close(); }
catch (Exception e) { e.printStackTrace(); }
}
return new DbAuthorization(userID);
}
在這個類中,可以看到抽象類和具體的子類之間的關(guān)系,它們是如何協(xié)作的,又是如何劃分抽象方法和非抽象方法的,這都是值得注重的地方。一般的,抽象方法需要子類來實現(xiàn),而抽象類中的非抽象方法應(yīng)該所有子類所能夠共享的,或者可是說,是定義在抽象方法之上的較高層的方法。這確實是一個抽象工廠的好例子!雖然實現(xiàn)的方法已經(jīng)和GOF中給出的實現(xiàn)相差較遠了,但思想沒變,這兒的實現(xiàn),也確實是要巧妙的些。
還有就是靜態(tài)方法的使用,使得這個類看起來有些Singleton的意味。這使得對于AbstractFactory的創(chuàng)建變得簡單。
在AuthorizationFactory中定義的其它方法,涉及到具體的如何創(chuàng)建Authorization,都是作為abstract方法出現(xiàn),具體實現(xiàn)留給子類來完成。
這樣,在需要生成一個Authorization的時候,只需要調(diào)用AuthorizationFactory的靜態(tài)方法getAuthorization就可以了,由子類實現(xiàn)了具體的細節(jié)。
其它的,如同上面講到的,在創(chuàng)建Forum的時候用的ForumFactory,具有同上面一樣的實現(xiàn),這就是模式之所以稱為模式的所在了。
資料引用:http://www.knowsky.com/365144.html
?
題目: IOC 后臺機制學(xué)習(xí)
給定:
配置文件 config.txt, 文件內(nèi)容
className = test.JavaBean1
field = username
value = ABC
該文件中的三個值會隨時可能變化, 唯一不變的是 className 指定的都是一個 JavaBean(為了簡化, 我們假定里面已經(jīng)有一個 username 屬性, 例如:
class JavaBeanxxxx {
?? ?private String username;
?? ?public String getUsername() {
?? ??? ?return username;
?? ?}
?? ?public void setUsername(String uname) {
?? ??? ?this.username = uname;
?? ?}
}
要求: 寫一段代碼, 讀取配置文件 config.txt, 然后實現(xiàn)把 className 指定的 JavaBean 類加載(注意這個類名是可以修改的, 可配置的), 然后生成一個實例,
并把配置文件中field字段指定的值作為這個實例的屬性名(這里是username)所對應(yīng)的值設(shè)置為 ABC(字符串), 并且要讀出最后設(shè)置的值.
此題已經(jīng)被 TigerTian 解答出來, 歡迎學(xué)習(xí), 也感謝 TigerTian:
package?com.gcoresoft.ioc;
import?java.io.*;
import?java.lang.reflect.*;
import?java.util.*;
import?java.beans.*;
public?class?IOCStudy?{
????
????//Load?the?properties?file
????private?Properties?prop=new?Properties();
????
????public?void?loadPropFile(String?filename)
????{
????????try
????????{
????????????FileInputStream?fin=new?FileInputStream(filename);
????????????prop.load(fin);
????????????fin.close();
????????}catch(Exception?e){
????????????System.out.println(e.toString());
????????}
????}
????
????private?String?getValueByName(String?Name)
????{
????????return?prop.getProperty(Name);
????}
????
????public?static?void?main(String[]?args)
????{
????????IOCStudy?ioc=new?IOCStudy();
????????ioc.loadPropFile("E:\\Work\\GetInIOC\\src\\com\\gcoresoft\\ioc\\Config.txt");
????????try
????????{
????????????Class?bean=Class.forName(ioc.getValueByName("className"));
????????????try?{
????????????????java.beans.BeanInfo?info=java.beans.Introspector.getBeanInfo(bean);
????????????????java.beans.PropertyDescriptor?pd[]=info.getPropertyDescriptors();
????????????????try?{
????????????????????Method?mSet=null,mRead=null;
????????????????????Object?obj=bean.newInstance();
????????????????????for(int?i=0;i<pd.length;i++)
????????????????????????if(pd[i].getName().equalsIgnoreCase(ioc.getValueByName("field")))
????????????????????????{
????????????????????????????mSet=pd[i].getWriteMethod();
????????????????????????????mRead=pd[i].getReadMethod();????????????????????????????
????????????????????????}
????????????????????try?{
????????????????????????mSet.invoke(obj,?ioc.getValueByName("value"));
????????????????????????String?str=(String)mRead.invoke(obj,?null);
????????????????????????System.out.println(str);
????????????????????}?catch?(IllegalArgumentException?e)?{
????????????????????????//?TODO?Auto-generated?catch?block
????????????????????????e.printStackTrace();
????????????????????}?catch?(InvocationTargetException?e)?{
????????????????????????//?TODO?Auto-generated?catch?block
????????????????????????e.printStackTrace();
????????????????????}
????????????????}?catch?(InstantiationException?e)?{
????????????????????//?TODO?Auto-generated?catch?block
????????????????????e.printStackTrace();
????????????????}?catch?(IllegalAccessException?e)?{
????????????????????//?TODO?Auto-generated?catch?block
????????????????????e.printStackTrace();
????????????????}
????????????????
????????????}?catch?(IntrospectionException?e)?{
????????????????//?TODO?Auto-generated?catch?block
????????????????e.printStackTrace();
????????????}
????????????
????????????
????????}catch(ClassNotFoundException?e){
????????????System.out.println(e.toString());
????????}
????????
????}
????
}
引言
在J2EE的整個發(fā)展歷程中,現(xiàn)在正是一個非常時刻。從很多方面來說,J2EE都是一個偉大的成功:它成功地在從前沒有標(biāo)準(zhǔn)的地方建立了標(biāo)準(zhǔn);大大提升了企業(yè)級軟件的開放程度,并且得到了整個行業(yè)和開發(fā)者的廣泛認可。然而,J2EE在一些方面已經(jīng)開始捉襟見肘。J2EE應(yīng)用開發(fā)的成本通常很高。J2EE應(yīng)用項目至少和從前的非J2EE項目一樣容易失敗——如果不是更容易失敗的話。這樣的失敗率高得讓人難以接受。在這樣的失敗率之下,軟件開發(fā)幾乎變成了碰運氣。而在J2EE遭遇失敗的場景中,EJB通常都扮演著重要的角色。因此,J2EE社群不斷地向著更簡單的解決方案、更少使用EJB的方向發(fā)展
[1]。然而,每個應(yīng)用程序都需要一些基礎(chǔ)設(shè)施,拒絕使用EJB并不意味著拒絕EJB所采用的基礎(chǔ)設(shè)施解決方案。那么,如何利用現(xiàn)有的框架來提供這些基礎(chǔ)設(shè)施服務(wù)呢,伴隨著這個問題的提出,一個輕量級的J2EE解決方案出現(xiàn)了,這就是Spring Framework。
Spring是為簡化企業(yè)級系統(tǒng)開發(fā)而誕生的,Spring框架為J2EE應(yīng)用常見的問題提供了簡單、有效的解決方案,使用Spring,你可以用簡單的POJO(Plain Old Java Object)來實現(xiàn)那些以前只有EJB才能實現(xiàn)的功能。這樣不只是能簡化服務(wù)器端開發(fā),任何Java系統(tǒng)開發(fā)都能從Spring的簡單、可測試和松耦合特征中受益。可以簡單的說,Spring是一個輕量級的反向控制(IoC)和面向切面編程(AOP)容器框架
[3]。Spring IoC,借助于依賴注入設(shè)計模式,使得開發(fā)者不用理會對象自身的生命周期及其關(guān)系,而且能夠改善開發(fā)者對J2EE模式的使用;Spring AOP,借助于Spring實現(xiàn)的攔截器,開發(fā)者能夠?qū)崿F(xiàn)以聲明的方式使用企業(yè)級服務(wù),比如安全性服務(wù)、事務(wù)服務(wù)等。Spring IoC和 Spring ; AOP組合,一起形成了Spring,這樣一個有機整體,使得構(gòu)建輕量級的J2EE架構(gòu)成為可能,而且事實證明,非常有效。
沒有Spring IoC的Spring AOP是不完善的,沒有Spring AOP的Spring IoC是不健壯的。本文是以Spring架構(gòu)的成功的實際商務(wù)系統(tǒng)項目為背景,闡述了反向控制原理和面向切面的編程技術(shù)在Spring框架中的應(yīng)用,同時抽取適量代碼示意具體應(yīng)用,并和傳統(tǒng)開發(fā)模式進行對比,展示了Spring framework的簡單,高效,可維護等優(yōu)點。
1、Spring IoC 1.1 反向控制原理 反向控制是Spring框架的核心。但是,反向控制是什么意思?到底控制的什么方面被反向了呢?2004年美國專家Martin Fowler發(fā)表了一篇論文《Inversion of Control Containers and the Dependency Injection pattern》闡述了這個問題,他總結(jié)說是獲得依賴對象的方式反向了,根據(jù)這個啟示,他還為反向控制提出了一個更貼切的名字:Dependency Injection(DI 依賴注入)。
通常,應(yīng)用代碼需要告知容器或框架,讓它們找到自身所需要的類,然后再由應(yīng)用代碼創(chuàng)建待使用的對象實例。因此,應(yīng)用代碼在使用實例之前,需要創(chuàng)建對象實例。然而,IoC模式中,創(chuàng)建對象實例的任務(wù)交給IoC容器或框架(實現(xiàn)了IoC設(shè)計模式的框架也被稱為IoC容器),使得應(yīng)用代碼只需要直接使用實例,這就是IoC。相對IoC 而言,“依賴注入”的確更加準(zhǔn)確的描述了這種設(shè)計理念。所謂依賴注入,即組件之間的依賴關(guān)系由容器在運行期決定,形象的來說,即由容器動態(tài)的將某種依賴關(guān)系注入到組件之中。
1.2 IoC在Spring中的實現(xiàn)
任何重要的系統(tǒng)都需要至少兩個相互合作的類來完成業(yè)務(wù)邏輯。通常,每個對象都要自己負責(zé)得到它的合作(依賴)對象。你會發(fā)現(xiàn),這樣會導(dǎo)致代碼耦合度高而且難于測試。使用IoC,對象的依賴都是在對象創(chuàng)建時由負責(zé)協(xié)調(diào)系統(tǒng)中各個對象的外部實體提供的,這樣使軟件組件松散連接成為可能。下面示意了Spring IoC 應(yīng)用,步驟如下:
?。?)定義Action接口,并為其定義一個execute方法,以完成目標(biāo)邏輯。多年前,GoF在《Design Pattern:Elements of Reusable Object-Oriented Software》一書中提出“Programming to an Interface,not an implementation”的原則,這里首先將業(yè)務(wù)對象抽象成接口,正是為了實施這個原則。
?。?)類UpperAction實現(xiàn)Action接口,在此類中,定義一個String型的域message,并提供相應(yīng)的setter和getter方法,實現(xiàn)的execute方法如下:
public String execute (String str) { return (getMessage () + str).toUpperCase () ; } |
?。?)編寫Spring配置文件(bean.xml)
<beans> <bean id="TheAction" class="net.chen.spring.qs.UpperAction"> <property name="message"> <value>HeLLo</value> </property> </bean> </beans> |
?。?)測試代碼
public void testQuickStart () { ApplicationContext ctx=new FileSystemXmlApplicationContext ("bean.xml"); Action a= (Action) ctx.getBean ("TheAction"); System.out.println (a. execute ("Rod Johnson")); } |
上面的測試代碼中,我們根據(jù)"bean.xml"創(chuàng)建了一個ApplicationContext實例,并從此實例中獲取我們所需的Action實現(xiàn),運行測試代碼,我們看到控制臺輸出:
仔細觀察一下上面的代碼,可以看到:
?。?)我們的組件并不需要實現(xiàn)框架指定的接口,因此可以輕松的將組件從Spring中脫離,甚至不需要任何修改,這在基于EJB框架實現(xiàn)的應(yīng)用中是難以想象的。
?。?)組件間的依賴關(guān)系減少,極大改善了代碼的可重用性。Spring的依賴注入機制,可以在運行期為組件配置所需資源,而無需在編寫組件代碼時就加以指定,從而在相當(dāng)程度上降低了組件之間的耦合。
Spring給我們帶來了如此這般的好處,那么,反過來,讓我們試想一下,如果不使用Spring框架,回到我們傳統(tǒng)的編碼模式,情況會是怎樣呢?
首先,我們必須編寫一個配置文件讀取類,以實現(xiàn)Message屬性的可配置化。
其次,得有一個Factory模式的實現(xiàn),并結(jié)合配置文件的讀寫完成Action的動態(tài)加載。于是,我們實現(xiàn)了一個ActionFactory來實現(xiàn)這個功能:
public class ActionFactory { public static Action getAction (String actionName) {Properties pro = new Properties (); try { pro.load (new FileInputStream ("config.properties")); String actionImplName =(String)pro.get(actionName); String actionMessage =(String) pro.get (actionName+"_msg"); Object obj =Class.forName (actionImplName).newInstance (); BeanUtils.setProperty(obj,"message",actionMessage); return (Action) obj; } catch (FileNotFoundException e) { …… } } |
配置文件則采用properties文件形式如下所示:
TheAction=net.chen.spring.qs.UpperAction TheAction_msg=HeLLo |
測試代碼也作相應(yīng)修改?,F(xiàn)在不論實現(xiàn)的好壞,總之通過上面新增的多行代碼,終于實現(xiàn)了類似的功能。如果現(xiàn)在有了一個新的需求,這樣這個ActionFactory每次都新建一個類的實例,顯然這對系統(tǒng)性能不利,考慮到我們的兩個Action都是線程安全的,修改一下ActionFactory,保持系統(tǒng)中只有一個Action實例供其它線程調(diào)用。另外Action對象創(chuàng)建后,需要做一些初始化工作。修改一下ActionFactory,使其在創(chuàng)建Action實例之后,隨即就調(diào)用Action.init方法執(zhí)行初始化。Action的處理這樣就差不多了。下面我們來看看另外一個Factory
……
往往這些系統(tǒng)開發(fā)中最常見的需求,會導(dǎo)致我們的代碼迅速膨脹,而Spring IoC的出現(xiàn),則大大緩解了這樣的窘境。通過以上實例,可以看出,Spring IoC為我們提供了如下幾方面的優(yōu)勢:
?。?)應(yīng)用組件不需要在運行時尋找其協(xié)作者,因此更易于開發(fā)和編寫應(yīng)用;
?。?)由于借助于IoC容器管理組件的依賴關(guān)系,使得應(yīng)用的單元測試和集成測試更利于展開;
?。?)通常,在借助于IoC容器關(guān)系業(yè)務(wù)對象的前提下,很少需要使用具體IoC容器提供的API,這使得集成現(xiàn)有的遺留應(yīng)用成為可能。
因此,通過使用IoC能夠降低組件之間的耦合度,最終,能夠提高類的重用性,利于測試,而且更利于整個產(chǎn)品或系統(tǒng)集成和配置。
2、Spring AOP
2.1 面向切面編程基礎(chǔ)
通常,系統(tǒng)由很多組件組成,每個組件負責(zé)一部分功能,然而,這些組件也經(jīng)常帶有一些除了核心功能之外的附帶功能 。系統(tǒng)服務(wù)如日志、事務(wù)管理和安全經(jīng)常融入到一些其他功能模塊中。這些系統(tǒng)服務(wù)通常叫做交叉業(yè)務(wù),這是因為它們總是分布在系統(tǒng)的很多組件中。通過將這些業(yè)務(wù)分布在多個組件中,給我們的代碼引入了雙重復(fù)雜性。
(1) 實現(xiàn)系統(tǒng)級業(yè)務(wù)的代碼在多個組件中復(fù)制。這意味著如果你要改變這些業(yè)務(wù)邏輯,你就必須到各個模塊去修改。就算把這些業(yè)務(wù)抽象成一個獨立模塊,其它模塊只是調(diào)用它的一個方法,但是這個方法調(diào)用也還是分布在很多地方。
(2) 組件會因為那些與自己核心業(yè)務(wù)無關(guān)的代碼變得雜亂。一個向地址錄中添加條目的方法應(yīng)該只關(guān)心如何添加地址,而不是關(guān)心它是不是安全或支持事務(wù)的。
此時,我們該怎么辦呢?這正是AOP用得著的地方。AOP幫助我們將這些服務(wù)模塊化,并把它們聲明式地應(yīng)用在需要它們的地方,使得這些組件更加專注于自身業(yè)務(wù),完全不知道其它涉及到的系統(tǒng)服務(wù)。
這里的概念切面,就是我們要實現(xiàn)的交叉功能,是應(yīng)用系統(tǒng)模塊化的一個方面或領(lǐng)域。切面的最常見例子就是日志記錄。日志記錄在系統(tǒng)中到處需要用到,利用繼承來重用日志模塊是不合適的,這樣,就可以創(chuàng)建一個日志記錄切面,并且使用AOP在系統(tǒng)中應(yīng)用。下圖展示了切面應(yīng)用方式

圖表 1 應(yīng)用切面
其中,通知Advice是切面的實際實現(xiàn)。連接點Joinpoint是應(yīng)用程序執(zhí)行過程中插入切面的地點,這個地點可以是方法調(diào)用,異常拋出,甚至可以是要修改的字段,切面代碼在這些地方插入到你的應(yīng)用流程中,添加新的行為。切入點Pointcut定義了Advice應(yīng)該應(yīng)用在那些連接點,通常通過指定類名和方法名,或者匹配類名和方法名式樣的正則表達式來指定切入點。
2.2 AOP在Spring中的實現(xiàn)
基于AOP,業(yè)界存在各種各樣的AOP實現(xiàn),比如,JBoss AOP、Spring AOP、AspectJ、Aspect Werkz等。各自實現(xiàn)的功能也不一樣。AOP實現(xiàn)的強弱在很大程度上取決于連接點模型。目前,Spring只支持方法級的連接點。這和一些其他AOP框架不一樣,如AspectJ和JBoss,它們還提供了屬性接入點,這樣可以防止你創(chuàng)建特別細致的通知,如對更新對象屬性值進行攔截。然而,由于Spring關(guān)注于提供一個實現(xiàn)J2EE服務(wù)的框架,所以方法攔截可以滿足大部分要求,而且Spring的觀點是屬性攔截破壞了封裝,讓Advice觸發(fā)在屬性值改變而不是方法調(diào)用上無疑是破壞了這個概念。
Spring的AOP框架的關(guān)鍵點如下:
?。?)Spring實現(xiàn)了AOP聯(lián)盟接口。在Spring AOP中,存在如下幾種通知(Advice)類型
Before通知:在目標(biāo)方法被調(diào)用前調(diào)用,涉及接口org.springframework.aop.MethodBeforeAdvice;
After通知:在目標(biāo)方法被調(diào)用后調(diào)用,涉及接口為org.springframework.aop.AfterReturningAdvice;
Throws通知:目標(biāo)方法拋出異常時調(diào)用,涉及接口org.springframework.aop.MethodBeforeAdvice;
Around通知:攔截對目標(biāo)對象方法調(diào)用,涉及接口為org.aopalliance.intercept.MethodInterceptor。
(2)用java編寫Spring通知,并在Spring的配置文件中,定義在什么地方應(yīng)用通知的切入點。
?。?)Spring的運行時通知對象。代理Bean只有在第一次被應(yīng)用系統(tǒng)需要的時候才被創(chuàng)建。如果你使用的是ApplicationContext,代理對象在BeanFactory載入所有Bean的時候被創(chuàng)建。Spring有兩種代理創(chuàng)建方式。如果目標(biāo)對象實現(xiàn)了一個或多個接口暴露的方法,Spring將使用JDK的java.lang.reflect.Proxy類創(chuàng)建代理。這個類讓Spring動態(tài)產(chǎn)生一個新的類,它實現(xiàn)所需的接口,織入了通知,并且代理對目標(biāo)對象的所有請求。如果目標(biāo)對象沒有實現(xiàn)任何接口,Spring使用CGLIB庫生成目標(biāo)對象的子類。在創(chuàng)建這個子類的時候,Spring將通知織入,并且將對目標(biāo)對象的調(diào)用委托給這個子類。此時,需要將Spring發(fā)行包lib/cglib目錄下的JAR文件發(fā)布到應(yīng)用系統(tǒng)中。
2.3 Spring AOP的優(yōu)勢
借助于Spring AOP,Spring IoC能夠很方便的使用到非常健壯、靈活的企業(yè)級服務(wù),是因為Spring AOP能夠提供如下幾方面的優(yōu)勢:
(1)允許開發(fā)者使用聲明式企業(yè)服務(wù),比如事務(wù)服務(wù)、安全性服務(wù);EJB開發(fā)者都知道,EJB組件能夠使用J2EE容器提供的聲明式服務(wù),但是這些服務(wù)要借助于EJB容器,而Spring AOP卻不需要EJB容器,借助于Spring的事務(wù)抽象框架就可以這些服務(wù)。
(2)開發(fā)者可以開發(fā)滿足業(yè)務(wù)需求的自定義切面;
(3)開發(fā)Spring AOP Advice很方便。因為這些AOP Advice僅是POJO類,借助于Spring提供的ProxyFactoryBean,能夠快速的搭建Spring AOP Advice。
3、結(jié)語 本文詳細闡述了Spring背后的IoC原理和AOP技術(shù),以實際成功項目為背景,抽取簡短片斷,展示了Spring架構(gòu)J2EE應(yīng)用系統(tǒng)的原理。Spring IoC借助于依賴注入機制,減輕了組件之間的依賴關(guān)系,同時也大大提高了組件的可移植性,組件得到了更多的重用機會。借助于Spring AOP,使得開發(fā)者能聲明式、基于元數(shù)據(jù)訪問企業(yè)級服務(wù),AOP合理補充了OOP技術(shù),Spring AOP合理地補充了Spring IoC容器。Spring IoC與Spring AOP組合,使得Spring成為成功的J2EE架構(gòu)框架,并能與標(biāo)準(zhǔn)的EJB等標(biāo)準(zhǔn)對抗,EJB不再是必需品。Spring已經(jīng)沖入了J2EE的核心,將引領(lǐng)整個J2EE開發(fā)、架構(gòu)的方向。
著名的EJB領(lǐng)域頂尖的專家Richard Monson-Haefel在其個人網(wǎng)站:www.EJBNow.com中極力推薦的GoF的《設(shè)計模式》,原文如下:
Design Patterns
Most developers claim to experience an epiphany reading this book. If you've never read the Design Patterns book then you have suffered a very serious gap in your programming education that should be remedied immediately.
翻譯: 很多程序員在讀完這本書,宣布自己相當(dāng)于經(jīng)歷了一次"主顯節(jié)"(紀(jì)念那穌降生和受洗的雙重節(jié)日),如果你從來沒有讀過這本書,你會在你的程序教育生涯里存在一個嚴(yán)重裂溝,所以你應(yīng)該立即挽救彌補!
可以這么說:GoF設(shè)計模式是程序員真正掌握面向?qū)ο蠛诵乃枷氲谋匦拚n。雖然你可能已經(jīng)通過了SUN的很多令人炫目的技術(shù)認證,但是如果你沒有學(xué)習(xí)掌握GoF設(shè)計模式,只能說明你還是一個技工。
在瀏覽《Thingking in Java》(第一版)時,你是不是覺得好象這還是一本Java基礎(chǔ)語言書籍?但又不純粹是,因為這本書的作者將面向?qū)ο蟮乃枷肭擅畹娜诤显贘ava的具體技術(shù)上,潛移默化的讓你感覺到了一種新的語言和新的思想方式的誕生。
但是讀完這本書,你對書中這些蘊含的思想也許需要一種更明晰更系統(tǒng)更透徹的了解和掌握,那么你就需要研讀GoF的《設(shè)計模式》了。
《Thingking in Java》(第一版中文)是這樣描述設(shè)計模式的:他在由Gamma, Helm和Johnson Vlissides簡稱Gang of Four(四人幫),縮寫GoF編著的《Design Patterns》一書中被定義成一個“里程碑”。事實上,那本書現(xiàn)在已成為幾乎所有OOP(面向?qū)ο蟪绦蛟O(shè)計)程序員都必備的參考書。(在國外是如此)。
GoF的《設(shè)計模式》是所有面向?qū)ο笳Z言(C++ Java C#)的基礎(chǔ),只不過不同的語言將之實現(xiàn)得更方便地使用。
GOF的設(shè)計模式是一座"橋"
就Java語言體系來說,GOF的設(shè)計模式是Java基礎(chǔ)知識和J2EE框架知識之間一座隱性的"橋"。
會Java的人越來越多,但是一直徘徊在語言層次的程序員不在少數(shù),真正掌握Java中接口或抽象類的應(yīng)用不是很多,大家經(jīng)常以那些技術(shù)只適合大型項目為由,避開或忽略它們,實際中,Java的接口或抽象類是真正體現(xiàn)Java思想的核心所在,這些你都將在GoF的設(shè)計模式里領(lǐng)略到它們變幻無窮的魔力。
GoF的設(shè)計模式表面上好象也是一種具體的"技術(shù)",而且新的設(shè)計模式不斷在出現(xiàn),設(shè)計模式自有其自己的發(fā)展軌道,而這些好象和J2EE .Net等技術(shù)也無關(guān)!
實際上,GoF的設(shè)計模式并不是一種具體"技術(shù)",它講述的是思想,它不僅僅展示了接口或抽象類在實際案例中的靈活應(yīng)用和智慧,讓你能夠真正掌握接口或抽象類的應(yīng)用,從而在原來的Java語言基礎(chǔ)上躍進一步,更重要的是,GoF的設(shè)計模式反復(fù)向你強調(diào)一個宗旨:要讓你的程序盡可能的可重用。
這其實在向一個極限挑戰(zhàn):軟件需求變幻無窮,計劃沒有變化快,但是我們還是要尋找出不變的東西,并將它和變化的東西分離開來,這需要非常的智慧和經(jīng)驗。
而GoF的設(shè)計模式是在這方面開始探索的一塊里程碑。
J2EE等屬于一種框架軟件,什么是框架軟件?它不同于我們以前接觸的Java API等,那些屬于Toolkist(工具箱),它不再被動的被使用,被調(diào)用,而是深刻的介入到一個領(lǐng)域中去,J2EE等框架軟件設(shè)計的目的是將一個領(lǐng)域中不變的東西先定義好,比如整體結(jié)構(gòu)和一些主要職責(zé)(如數(shù)據(jù)庫操作 事務(wù)跟蹤 安全等),剩余的就是變化的東西,針對這個領(lǐng)域中具體應(yīng)用產(chǎn)生的具體不同的變化需求,而這些變化東西就是J2EE程序員所要做的。
由此可見,設(shè)計模式和J2EE在思想和動機上是一脈相承,只不過
1.設(shè)計模式更抽象,J2EE是具體的產(chǎn)品代碼,我們可以接觸到,而設(shè)計模式在對每個應(yīng)用時才會產(chǎn)生具體代碼。
2.設(shè)計模式是比J2EE等框架軟件更小的體系結(jié)構(gòu),J2EE中許多具體程序都是應(yīng)用設(shè)計模式來完成的,當(dāng)你深入到J2EE的內(nèi)部代碼研究時,這點尤其明顯,因此,如果你不具備設(shè)計模式的基礎(chǔ)知識(GoF的設(shè)計模式),你很難快速的理解J2EE。不能理解J2EE,如何能靈活應(yīng)用?
3.J2EE只是適合企業(yè)計算應(yīng)用的框架軟件,但是GoF的設(shè)計模式幾乎可以用于任何應(yīng)用!因此GoF的設(shè)計模式應(yīng)該是J2EE的重要理論基礎(chǔ)之一。
所以說,GoF的設(shè)計模式是Java基礎(chǔ)知識和J2EE框架知識之間一座隱性的"橋"。為什么說隱性的?
GOF的設(shè)計模式是一座隱性的"橋"
因為很多人沒有注意到這點,學(xué)完Java基礎(chǔ)語言就直接去學(xué)J2EE,有的甚至鴨子趕架,直接使用起Weblogic等具體J2EE軟件,一段時間下來,發(fā)現(xiàn)不過如此,挺簡單好用,但是你真正理解J2EE了嗎?你在具體案例中的應(yīng)用是否也是在延伸J2EE的思想?
如果你不能很好的延伸J2EE的思想,那你豈非是大炮轟蚊子,認識到J2EE不是適合所有場合的人至少是明智的,但我們更需要將J2EE用對地方,那么只有理解J2EE此類框架軟件的精髓,那么你才能真正靈活應(yīng)用Java解決你的問題,甚至構(gòu)架出你自己企業(yè)的框架來。(我們不能總是使用別人設(shè)定好的框架,為什么不能有我們自己的框架?)
因此,首先你必須掌握GoF的設(shè)計模式。雖然它是隱性,但不是可以越過的。
?
關(guān)于本站“設(shè)計模式”
Java提供了豐富的API,同時又有強大的數(shù)據(jù)庫系統(tǒng)作底層支持,那么我們的編程似乎變成了類似積木的簡單"拼湊"和調(diào)用,甚至有人提倡"藍領(lǐng)程序員",這些都是對現(xiàn)代編程技術(shù)的不了解所至.
在真正可復(fù)用的面向?qū)ο缶幊讨?GoF的《設(shè)計模式》為我們提供了一套可復(fù)用的面向?qū)ο蠹夹g(shù),再配合Refactoring(重構(gòu)方法),所以很少存在簡單重復(fù)的工作,加上Java代碼的精煉性和面向?qū)ο蠹儩嵭?設(shè)計模式是java的靈魂),編程工作將變成一個讓你時刻體驗創(chuàng)造快感的激動人心的過程.
為能和大家能共同探討"設(shè)計模式",我將自己在學(xué)習(xí)中的心得寫下來,只是想幫助更多人更容易理解GoF的《設(shè)計模式》。由于原著都是以C++為例, 以Java為例的設(shè)計模式基本又都以圖形應(yīng)用為例,而我們更關(guān)心Java在中間件等服務(wù)器方面的應(yīng)用,因此,本站所有實例都是非圖形應(yīng)用,并且順帶剖析Jive論壇系統(tǒng).同時為降低理解難度,盡量避免使用UML圖.
如果你有一定的面向?qū)ο缶幊探?jīng)驗,你會發(fā)現(xiàn)其中某些設(shè)計模式你已經(jīng)無意識的使用過了;如果你是一個新手,那么從開始就培養(yǎng)自己良好的編程習(xí)慣(讓你的的程序使用通用的模式,便于他人理解;讓你自己減少重復(fù)性的編程工作),這無疑是成為一個優(yōu)秀程序員的必備條件.
整個設(shè)計模式貫穿一個原理:面對接口編程,而不是面對實現(xiàn).目標(biāo)原則是:降低耦合,增強靈活性.
所謂MIS(管理信息系統(tǒng)--Management Information System)系統(tǒng),是一個由人、計算機及其他外圍設(shè)備等組成的能進行信息的收集、傳遞、存貯、加工、維護和使用的系統(tǒng)。它是一門新興的科學(xué),其主要任務(wù)是最大限度的利用現(xiàn)代計算機及網(wǎng)絡(luò)通訊技術(shù)加強企業(yè)的信息管理,通過對企業(yè)擁有的人力、物力、財力、設(shè)備、技術(shù)等資源的調(diào)查了解,建立正確的數(shù)據(jù),加工處理并編制成各種信息資料及時提供給管理人員,以便進行正確的決策,不斷提高企業(yè)的管理水平和經(jīng)濟效益。目前,企業(yè)的計算機網(wǎng)絡(luò)已成為企業(yè)進行技術(shù)改造及提高企業(yè)管理水平的重要手段。隨著我國與世界信息高速公路的接軌,企業(yè)通過計算機網(wǎng)絡(luò)獲得信息必將為企業(yè)帶來巨大的經(jīng)濟效益和社會效益,企業(yè)的辦公及管理都將朝著高效、快速、無紙化的方向發(fā)展。MIS系統(tǒng)通常用于系統(tǒng)決策,例如,可以利用MIS系統(tǒng)找出目前迫切需要解決的問題,并將信息及時反饋給上層管理人員,使他們了解當(dāng)前工作發(fā)展的進展或不足。換句話說,MIS系統(tǒng)的最終目的是使管理人員及時了解公司現(xiàn)狀,把握將來的發(fā)展路徑。
一個完整的MIS應(yīng)包括:輔助決策系統(tǒng)(DSS)、工業(yè)控制系統(tǒng)(IPC)、辦公自動化系統(tǒng)(OA)以及數(shù)據(jù)庫、模型庫、方法庫、知識庫和與上級機關(guān)及外界交換信息的接口。其中,特別是辦公自動化系統(tǒng)(OA)、與上級機關(guān)及外界交換信息等都離不開Intranet的應(yīng)用。可以這樣說,現(xiàn)代企業(yè)MIS不能沒有 Intranet,但Intranet的建立又必須依賴于MIS的體系結(jié)構(gòu)和軟硬件環(huán)境。
傳統(tǒng)的MIS系統(tǒng)的核心是CS (Client/Server——客戶端/服務(wù)器)架構(gòu),而基于Internet的MIS系統(tǒng)的核心是BS(Browser/Server——瀏覽器/服務(wù)器)架構(gòu)。BS架構(gòu)比起CS架構(gòu)有著很大的優(yōu)越性,傳統(tǒng)的MIS系統(tǒng)依賴于專門的操作環(huán)境,這意味著操作者的活動空間受到極大限制;而BS架構(gòu)則不需要專門的操作環(huán)境,在任何地方,只要能上網(wǎng),就能夠操作MIS系統(tǒng),這其中的優(yōu)劣差別是不言而喻的。
基于Internet上的 MIS系統(tǒng)是對傳統(tǒng)MIS系統(tǒng)概念上的擴展,它不僅可以用于高層決策,而且可以用于進行普通的商務(wù)管理。通過用戶的具名登錄(或匿名登錄),以及相應(yīng)的權(quán)限控制,可以實現(xiàn)在遠端對系統(tǒng)的瀏覽、查詢、控制和審閱。隨著Internet的擴展,現(xiàn)有的公司和學(xué)校不再局限于物理的有形的真實的地域,網(wǎng)絡(luò)本身成為事實上發(fā)展的空間?;贗nternet上的MIS系統(tǒng),彌補了傳統(tǒng)MIS系統(tǒng)的不足,充分體現(xiàn)了現(xiàn)代網(wǎng)絡(luò)時代的特點。隨著Internet技術(shù)的高速發(fā)展,因特網(wǎng)必將成為人類新社會的技術(shù)基石?;贗nternet的MIS系統(tǒng)必將成為網(wǎng)絡(luò)時代的新一代管理信息系統(tǒng),前景極為樂觀
國外開發(fā)者博客中有一篇有趣的文章,將程序員按水平像軟件版本號那樣劃分為不同的版本。相對于在招聘時分為初級,中級,高級程序員,直接表明需要某種語言N版本的程序員或許更方便直接。根據(jù)作者的觀點,可將WEB開發(fā)者大致分為以下幾個版本:
Alpha:閱讀過一些專業(yè)書籍,大多數(shù)能用Dreamweaver或者FrontPage幫朋友制作一些Web頁面。但在他們熟練掌握HTML代碼以前,你大概不會雇傭他們成為職業(yè)的WEB制作人員。
Beta:已經(jīng)比較擅長整合站點頁面了,在HTML技巧方面也有一定造詣,但還是用Tables來制作頁面,不了解CSS,在面對動態(tài)頁面或數(shù)據(jù)庫連接時還是底氣不足。
Pre Version 1 (0.1):比Beta版的開發(fā)者水平要高。熟悉HTML,開始了解CSS是如何運作的,懂一點JavaScript,但還是基于業(yè)余水準(zhǔn),逐步開始關(guān)心動態(tài)站點搭建和數(shù)據(jù)庫連接的知識。這個版本的WEB開發(fā)人員還遠不能成為雇主眼中的香餑餑。
1.0: 能夠基本把控整個站點開發(fā),針對每個問題盡可能的找到最直接的解決辦法。但對可測性,可擴展性以及在不同(層)框架下如何選擇最合適的WEB設(shè)計工具尚無概念。這個版本的WEB開發(fā)者有良好的技術(shù)基礎(chǔ),需要有進一步的幫助和指導(dǎo)。

2.0:懂面向?qū)ο蟮木幊陶Z言,理解分層開發(fā)的必要性,關(guān)注代碼分離,對問題尋找更完美的解決方法,偶然也會考慮設(shè)計模式的問題,但對此仍然概念不清。屬于優(yōu)秀的初級開發(fā)者,能完成較松散的代碼開發(fā)(相對大型嚴(yán)謹(jǐn)?shù)恼军c開發(fā)而言),在面對較復(fù)雜問題尋找解決辦法時需要周邊人的幫助。
3.0:開始較為深入的理解面向?qū)ο缶幊毯驮O(shè)計模式,了解他們的用途,當(dāng)看到好的設(shè)計模式時能看透其本質(zhì),逐步關(guān)注分層的架構(gòu)解決辦法和可測試性。理解不同的開發(fā)語言并能說出他們的異同(例如各自的優(yōu)勢)。屬于優(yōu)秀的中級別開發(fā)者,雇主也確信他們最終能找到問題的解決辦法,這個版本的人可以給1.0和2.0的開發(fā)者以指導(dǎo)。但他們對架構(gòu)的理解仍然不夠清晰,值得一提的是,只要給予一些指導(dǎo),他們能很快理解并熟記做出的決定,以及選定方案的優(yōu)勢所在。
4.0:
理解模式,重視用戶的反饋。著手研究方法論,架構(gòu)設(shè)計和軟件開發(fā)的最佳入口。頭腦中已經(jīng)形成了超越開發(fā)語言,技術(shù)架構(gòu)的整體方案,可根據(jù)需求解構(gòu)程序。能從理論的角度,不同模式如何融合成最佳形態(tài),將多種X-驅(qū)動的模式應(yīng)用到不同的方案中。是精通多語言的高手,理解不同系統(tǒng)和方法論的細微差別,屬于高級程序員。這個級別的人能夠輕易的輔導(dǎo)2.0和3.0的程序員,將他們推向更高的級別。
5.0:從系統(tǒng)的角度考慮問題。對各種系統(tǒng)結(jié)構(gòu)有深入研究,能對整個代碼架構(gòu)中的問題進行改進。在團隊粘合性以及代碼安全性方面有杰出貢獻。對1.0到4.0版本的開發(fā)人員出現(xiàn)的問題能及時察覺,讓整個團隊保持積極性且保持興奮的狀態(tài)創(chuàng)建軟件解決辦法。舉例來說,他們總是對新的技術(shù)和信息保持饑渴狀態(tài),試圖用最簡便的方案解決開發(fā)任務(wù)。在整個IT團隊中獲得信任,屬于高級程序員和架構(gòu)師。
那么,您屬于哪個版本的程序員呢?
感謝Wendal,匿名人士的投遞
Eclipse官方網(wǎng)站已經(jīng)正式宣布 Eclipse 3.4發(fā)布,代號為ganymede (Ganymede (英語發(fā)音"GAN uh meed")為最大的木星已知衛(wèi)星,也是第七顆發(fā)現(xiàn)的木星衛(wèi)星,在伽利略發(fā)現(xiàn)的衛(wèi)星中離木星第三近,在希臘神話中 Ganymede是一個特洛伊美人的男孩(一個美少男),被宙斯帶去給眾神斟酒)。
?
關(guān)注Eclipse項目的開發(fā)者朋友們可以下載3.4版本嘗試一下,在JavaEye上還專門介紹一個很酷的Eclipse3.4帶的實時結(jié)對編程插件
目前3.4版本是Eclipse項目發(fā)布的10周年慶典版;至今Eclipse項目共有23個子項目。此次發(fā)布的Ganymede 版本引入不少亮點,其中包括新的p2平臺(provisioning platform),點擊查看p2的介紹、新增的Equinox(OSGi實現(xiàn))安全方面的特性、全新的Ecore建模工具、支持SOA等。