#
這是一堂關(guān)于UML基礎(chǔ)知識的補習課;現(xiàn)在我們做項目時間都太緊了,基本上都沒有做過真正的class級別的詳細設(shè)計,更別提使用UML來實現(xiàn)規(guī)范建模了;本篇主要就以前自己一直感覺很迷糊的幾種class之間的關(guān)系進行整理,讓我們在真正用UML進行比如類圖設(shè)計時能夠更加清晰明了;以下就分別介紹這幾種關(guān)系:
繼承
指的是一個類(稱為子類、子接口)繼承另外的一個類(稱為父類、父接口)的功能,并可以增加它自己的新功能的能力,繼承是類與類或者接口與接口之間最常見的關(guān)系;在Java中此類關(guān)系通過關(guān)鍵字extends明確標識,在設(shè)計時一般沒有爭議性;

實現(xiàn)
指的是一個class類實現(xiàn)interface接口(可以是多個)的功能;實現(xiàn)是類與接口之間最常見的關(guān)系;在Java中此類關(guān)系通過關(guān)鍵字implements明確標識,在設(shè)計時一般沒有爭議性;

依賴
可以簡單的理解,就是一個類A使用到了另一個類B,而這種使用關(guān)系是具有偶然性的、、臨時性的、非常弱的,但是B類的變化會影響到A;比如某人要過河,需要借用一條船,此時人與船之間的關(guān)系就是依賴;表現(xiàn)在代碼層面,為類B作為參數(shù)被類A在某個method方法中使用;

關(guān)聯(lián)
他體現(xiàn)的是兩個類、或者類與接口之間語義級別的一種強依賴關(guān)系,比如我和我的朋友;這種關(guān)系比依賴更強、不存在依賴關(guān)系的偶然性、關(guān)系也不是臨時性的,一般是長期性的,而且雙方的關(guān)系一般是平等的、關(guān)聯(lián)可以是單向、雙向的;表現(xiàn)在代碼層面,為被關(guān)聯(lián)類B以類屬性的形式出現(xiàn)在關(guān)聯(lián)類A中,也可能是關(guān)聯(lián)類A引用了一個類型為被關(guān)聯(lián)類B的全局變量;

聚合
聚合是關(guān)聯(lián)關(guān)系的一種特例,他體現(xiàn)的是整體與部分、擁有的關(guān)系,即has-a的關(guān)系,此時整體與部分之間是可分離的,他們可以具有各自的生命周期,部分可以屬于多個整體對象,也可以為多個整體對象共享;比如計算機與CPU、公司與員工的關(guān)系等;表現(xiàn)在代碼層面,和關(guān)聯(lián)關(guān)系是一致的,只能從語義級別來區(qū)分;

組合
組合也是關(guān)聯(lián)關(guān)系的一種特例,他體現(xiàn)的是一種contains-a的關(guān)系,這種關(guān)系比聚合更強,也稱為強聚合;他同樣體現(xiàn)整體與部分間的關(guān)系,但此時整體與部分是不可分的,整體的生命周期結(jié)束也就意味著部分的生命周期結(jié)束;比如你和你的大腦;表現(xiàn)在代碼層面,和關(guān)聯(lián)關(guān)系是一致的,只能從語義級別來區(qū)分;

對于繼承、實現(xiàn)這兩種關(guān)系沒多少疑問,他們體現(xiàn)的是一種類與類、或者類與接口間的縱向關(guān)系;其他的四者關(guān)系則體現(xiàn)的是類與類、或者類與接口間的引用、橫向關(guān)系,是比較難區(qū)分的,有很多事物間的關(guān)系要想準備定位是很難的,前面也提到,這幾種關(guān)系都是語義級別的,所以從代碼層面并不能完全區(qū)分各種關(guān)系;但總的來說,后幾種關(guān)系所表現(xiàn)的強弱程度依次為:組合>聚合>關(guān)聯(lián)>依賴;
大多數(shù)并發(fā)應用程序是以執(zhí)行任務(task)為基本單位進行管理的。通常情況下,我們會為每個任務單獨創(chuàng)建一個線程來執(zhí)行。這樣會帶來兩個問題:一,大量的線程(>100)會消耗系統(tǒng)資源,使線程調(diào)度的開銷變大,引起性能下降;二,對于生命周期短暫的任務,頻繁地創(chuàng)建和消亡線程并不是明智的選擇。因為創(chuàng)建和消亡線程的開銷可能會大于使用多線程帶來的性能好處。
一個比較簡單的線程池至少應包含線程池管理器、工作線程、任務隊列、任務接口等部分。其中線程池管理器(ThreadPool Manager)的作用是創(chuàng)建、銷毀并管理線程池,將工作線程放入線程池中;工作線程是一個可以循環(huán)執(zhí)行任務的線程,在沒有任務時進行等待;任務隊列的作用是提供一種緩沖機制,將沒有處理的任務放在任務隊列中;任務接口是每個任務必須實現(xiàn)的接口,主要用來規(guī)定任務的入口、任務執(zhí)行完后的收尾工作、任務的執(zhí)行狀態(tài)等,工作線程通過該接口調(diào)度任務的執(zhí)行。下面的代碼實現(xiàn)了創(chuàng)建一個線程池,以及從線程池中取出線程的操作。
在多線程大師Doug Lea的貢獻下,在JDK1.5中加入了許多對并發(fā)特性的支持,例如:線程池。
1.核心線程(任務):我們定義的線程,即實現(xiàn)了Runnable接口的類,是我們將要放到線程池中執(zhí)行的類,如實例代碼中的CountService類
2.工作線程:由線程池中創(chuàng)建的線程,是用來獲得核心線程并執(zhí)行核心線程的線程(比較拗口哦,具體看代碼就知道是什么東東了)。
簡單理解就三個概念:線程、線程池和任務。任務:就是要執(zhí)行的業(yè)務邏輯;線程:任務是要放到線程中去執(zhí)行的;線程池:主要是控制當前正在執(zhí)行的線程的數(shù)量和將要被執(zhí)行的線程隊列。一、簡介
線程池類為 java.util.concurrent.ThreadPoolExecutor,常用構(gòu)造方法為:
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize,long keepAliveTime, TimeUnit unit,BlockingQueue<Runnable> workQueue,RejectedExecutionHandler handler)corePoolSize: 線程池維護線程的最少數(shù)量
maximumPoolSize:線程池維護線程的最大數(shù)量
keepAliveTime: 線程池維護線程所允許的空閑時間
unit: 線程池維護線程所允許的空閑時間的單位
workQueue: 線程池所使用的緩沖隊列
handler: 線程池對拒絕任務的處理策略
一個任務通過 execute(Runnable)方法被添加到線程池,任務就是一個 Runnable類型的對象,任務的執(zhí)行方法就是 Runnable類型對象的run()方法。
當一個任務通過execute(Runnable)方法欲添加到線程池時:
如果此時線程池中的數(shù)量小于corePoolSize,即使線程池中的線程都處于空閑狀態(tài),也要創(chuàng)建新的線程來處理被添加的任務。
如果此時線程池中的數(shù)量等于 corePoolSize,但是緩沖隊列 workQueue未滿,那么任務被放入緩沖隊列。
如果此時線程池中的數(shù)量大于corePoolSize,緩沖隊列workQueue滿,并且線程池中的數(shù)量小于maximumPoolSize,建新的線程來處理被添加的任務。
如果此時線程池中的數(shù)量大于corePoolSize,緩沖隊列workQueue滿,并且線程池中的數(shù)量等于maximumPoolSize,那么通過 handler所指定的策略來處理此任務。
也就是:處理任務的優(yōu)先級為:
核心線程corePoolSize、任務隊列workQueue、最大線程maximumPoolSize,如果三者都滿了,使用handler處理被拒絕的任務。
當線程池中的線程數(shù)量大于 corePoolSize時,如果某線程空閑時間超過keepAliveTime,線程將被終止。這樣,線程池可以動態(tài)的調(diào)整池中的線程數(shù)。
unit可選的參數(shù)為java.util.concurrent.TimeUnit中的幾個靜態(tài)屬性:
NANOSECONDS、MICROSECONDS、MILLISECONDS、SECONDS。
workQueue我常用的是:java.util.concurrent.ArrayBlockingQueue
handler有四個選擇:
ThreadPoolExecutor.AbortPolicy()
拋出java.util.concurrent.RejectedExecutionException異常
ThreadPoolExecutor.CallerRunsPolicy()
重試添加當前的任務,他會自動重復調(diào)用execute()方法
ThreadPoolExecutor.DiscardOldestPolicy()
拋棄舊的任務
ThreadPoolExecutor.DiscardPolicy()
拋棄當前的任務
二、一般用法舉例
package com.paul.threadPool;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;


public class TestThreadPool
{
private static int produceTaskSleepTime = 10;
private static int produceTaskMaxNumber = 10;

public static void main(String[] args)
{
// 構(gòu)造一個線程池
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2, 4, 3,
TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(3),
new ThreadPoolExecutor.CallerRunsPolicy());

for (int i = 1; i <= produceTaskMaxNumber; i++)
{

try
{
String task = "task@ " + i;
System.out.println("創(chuàng)建任務并提交到線程池中:" + task);
threadPool.execute(new ThreadPoolTask(task));
Thread.sleep(produceTaskSleepTime);

} catch (Exception e)
{
e.printStackTrace();
}
}
}
}
package com.paul.threadPool;

import java.io.Serializable;


public class ThreadPoolTask implements Runnable, Serializable
{

private static final long serialVersionUID = 0;
// 保存任務所需要的數(shù)據(jù)
private Object threadPoolTaskData;

private static int consumeTaskSleepTime = 2000;


ThreadPoolTask(Object tasks)
{
this.threadPoolTaskData = tasks;
}


public synchronized void run()
{
// 處理一個任務,這里的處理方式太簡單了,僅僅是一個打印語句
System.out.println("開始執(zhí)行任務:" + threadPoolTaskData);

try
{
// //便于觀察,等待一段時間
Thread.sleep(consumeTaskSleepTime);

} catch (Exception e)
{
e.printStackTrace();
}
threadPoolTaskData = null;
}


public Object getTask()
{
return this.threadPoolTaskData;
}

}說明:
1、在這段程序中,一個任務就是一個Runnable類型的對象,也就是一個ThreadPoolTask類型的對象。
2、一般來說任務除了處理方式外,還需要處理的數(shù)據(jù),處理的數(shù)據(jù)通過構(gòu)造方法傳給任務。
3、在這段程序中,main()方法相當于一個殘忍的領(lǐng)導,他派發(fā)出許多任務,丟給一個叫 threadPool的任勞任怨的小組來做。
這個小組里面隊員至少有兩個,如果他們兩個忙不過來,任務就被放到任務列表里面。
如果積壓的任務過多,多到任務列表都裝不下(超過3個)的時候,就雇傭新的隊員來幫忙。但是基于成本的考慮,不能雇傭太多的隊員,至多只能雇傭 4個。
如果四個隊員都在忙時,再有新的任務,這個小組就處理不了了,任務就會被通過一種策略來處理,我們的處理方式是不停的派發(fā),直到接受這個任務為止(更殘忍!呵呵)。
因為隊員工作是需要成本的,如果工作很閑,閑到 3SECONDS都沒有新的任務了,那么有的隊員就會被解雇了,但是,為了小組的正常運轉(zhuǎn),即使工作再閑,小組的隊員也不能少于兩個。
4、通過調(diào)整 produceTaskSleepTime和 consumeTaskSleepTime的大小來實現(xiàn)對派發(fā)任務和處理任務的速度的控制,改變這兩個值就可以觀察不同速率下程序的工作情況。
5、通過調(diào)整4中所指的數(shù)據(jù),再加上調(diào)整任務丟棄策略,換上其他三種策略,就可以看出不同策略下的不同處理方式。
6、對于其他的使用方法,參看jdk的幫助,很容易理解和使用。
摘要: 有依賴的包管理,可以部署到TOMCAT 6.X,可以使用JETTY作開發(fā)測試,可以生成站點,作CHECK STYLE,PMD代碼檢查,代碼覆蓋率,生成JAVA DOC。
Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--><project ...
閱讀全文
使用maven的一個方便之處是可以使用Jetty Plugin來運行web項目。只要maven jetty:run就可以把web項目跑起來了。只是很多時候我們都需要在IDE中進行調(diào)試。那如何在Eclipse中調(diào)試使用jetty Plugin的web項目呢?
下面我們就來配置一下。
- 首先在Run->Externel Tools->Open Externel Tools Dialog.. 打開配置對話框,選中左邊的Program節(jié)點,右鍵選擇New然后再右邊的配置里面輸入Name信息,在Main tab下的Location選擇你maven可執(zhí)行文件的全路徑(eg:/home/rory/apps/apache-maven-2.0.8/bin/mvn),Working Directory選擇你的maven項目(eg:${workspace_loc:/guice-example}),Arguments里輸入jetty:run。然后再切換到Environment tab。New 一下變量,name是
MAVEN_OPTS
value是
-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8080,server=y,suspend=y
ok,這一步設(shè)置完畢,Apply一下,close關(guān)閉
- 接下來添加一個Debug,打開Run->Open Debug Dialog..打開Debug Dialog窗口,選中左邊的Remote Java Application,右鍵New輸入name,Project里選中要Debug的項目Connection Properties里的Host里設(shè)置成localhost,Port設(shè)置成上面配置的8080(這里要填JETTY默認啟動的端口)然后Apply一下就ok了。
- 接下來就可以開始調(diào)試了。首先啟動第一步配置的Externel Tools配置,然后再運行第二步配置的Debug.就可以看到控制臺有mvn jetty:run的輸出了。接下來就開如Debug你的項目吧。:)
The motivation behind the framework
We had worked on a project where we hand-coded all of our DAOs. This produced four irksome difficulties: (1) Method names and implementations were not altogether consistent. (2) It was a pain to make additional columns sortable or filterable, and as a result, a lot of pages lacked good sorting and filtering. (3) Making additional DAOs was tedious and took a fair amount of time. (4) Writing tests for DAOs is tricky and tedious, so no one really did.
This framework aims to ease our troubles.
Why might you consider looking into this framework?
- Generic DAO: With the sweetness of Java generics, the concept of generic DAOs is not new, and it’s not difficult. However, we’ve put a lot of work into making these easy to use and robust. So if you like the way we’ve done it, then this framework provides ready-made code for you. On the other hand if you’d rather make your own, then simply feel free to look at our source code for ideas and help on a few potentially tricky issues.
- Search: Search is the most original and sophisticated part of this framework, and it can be used with or without the generic DAO portion of the framework. The search capability is designed around the use-case of a list page with sorting, filtering, column selection and paging. However, its use is certainly not limited to that. The value that the search adds is simpler, more robust querying with less coding and less testing. It is similar to Hibernate Criteria, but it is simpler to use and can easily move across layers of an application including view and even remote layers. Plus is works with both Hibernate and JPA*.
- Remote DAO (for R.I.A.s?): If you you’re like us, you don’t want to write and configure an individual DAO style remote service for each entity in a R.I.A. or other client-heavy application. This framework may have the solution. We provide utilities and sample code to adapt our single general DAO to any remoting technology interface. Just configure this single remote access point and the client can do any basic CRUD or search operation on any entity. Again, if you don’t like our way of doing things, maybe you can at least get some ideas from our source code.
- Remote Search (for R.I.A.s?): As mentioned above, the framework can provide a single point for client-server CRUD and search operations. The framework’s search is meant to be able to cross the client-server boundary. So lists and searches in the client application can take advantage of the same easy-to-use features and consistency that the search functionality provides in the server tier or single tier application. This consistency allowed us to create a reusable collection type in Adobe Flex 3 that is associated with a single search object and automatically updates itself from the server according to the search parameters.**
*A fairly simple adapter is required for each JPA provider. Right now we only have an adapter for Hibernate Entity Manager. If anyone would like to contribute an adapter for any other JPA provider (OpenJPA, TopLink, etc.), that would be great.
**If time permits, we would like to eventually post our corresponding Adobe Flex 3 framework and utilities.
More Information
Wiki Documentation: UserGuide
Javadoc: http://hibernate-generic-dao.googlecode.com/svn/trunk/docs/api/index.html
Blog: http://hibernategenericdao.wordpress.com/
Questions and Comments
Please post at http://groups.google.com/group/java-generic-dao.
Code Examples
Creating DAOs for individual model classes:
Simply extend the GenericDAO class with the specific type.

public interface ProjectDAO extends GenericDAO<Project, Long>
{

}


public class ProjectDAOImpl extends GenericDAOImpl<Project, Long> implements ProjectDAO
{

}
The following methods (and several more) are now available on ProjectDAO
Project project = projectDAO.find(projectId);
List<Project> list = projectDAO.findAll();
projectDAO.save(project);
projectDAO.remove(project);
projectDAO.removeById(project.getId());
Search search = new Search();
search.addFilterEqual("name", "hibernate-generic-dao");
List<Project> list = projectDAO.search(search);
int count = projectDAO.count(search);
SearchResult<Project> result = projectDAO.searchAndCount(search);
list = result.getResult();
count = result.getTotalCount();
search.clear();
search.addField("rating", Field.OP_AVG);
int avgProjectRating = (Integer) prjoectDAO.searchUnique(search);
A GeneralDAO is also provided with DAO methods for any entity:

public interface GeneralDAO
{
public <T> T find(Class<T> type, Serializable id);
public <T> T[] find(Class<T> type, Serializable ids);
public <T> T getReference(Class<T> type, Serializable id);
public <T> T[] getReferences(Class<T> type, Serializable ids);
public boolean save(Object entity); public boolean[] save(Object entities);
public boolean remove(Object entity); public void remove(Object entities);
public boolean removeById(Class<?> type, Serializable id);
public void removeByIds(Class<?> type, Serializable ids);
public <T> List<T> findAll(Class<T> type);
public List search(ISearch search); public Object searchUnique(ISearch search);
public int count(ISearch search); public SearchResult searchAndCount(ISearch search);
public boolean isAttached(Object entity);
public void refresh(Object entities); public void flush();
public Filter getFilterFromExample(Object example);
public Filter getFilterFromExample(Object example, ExampleOptions options); }
Search DTO usage examples
Search search = new Search(Project.class);

//filtering
search.addFilterEqual("name", "hibernate-generic-dao");

search.addFilterLessThan("completionDate", new Date());

search.addFilterOr(
Filter.equal("name", "Jack"),
Filter.and(
Filter.equal("name", "Jill"),
Filter.like("location", "%Chicago%"),
Filter.greaterThan("age", 5) )
);

search.addFilterIn("name", "Jack", "Jill", "Bob");

search.addFilterNot(Filter.in("name","Jack", "Jill", "Bob"));

//sorting
search.addSort("name");
search.addSort("age", true); //descending

//projection
search.addField("name");
search.addField("location");

//or with column operators
search.addField("rating", Field.OP_AVG);
search.addField("developerCount", Field.OP_MAX);

//paging
search.setMaxResults(15); //a.k.a. results per page
search.setPage(3);

//controlling eager fetching of relationships
serach.addFetch("owner");
Nested properties are also fully supported...
search.addFilterEqua("status.name", "active");
search.addFilterGreaterThan("workgroup.manager.salary", 75000.00);
search.addSort("status.name");
Installation
Step 1 (download):
Download the file javaee5-maven-archetype-1.0.jar
Step 2 (install in local repo):
Run:
mvn install:install-file -Dfile=javaee5-maven-archetype-1.0.jar -DgroupId=pl.piotrsorobka.maven -DartifactId=javaee5-maven-archetype -Dversion=1.0 -Dpackaging=jar -DgeneratePom=true
Using the archetype
Run:
mvn archetype:create -DarchetypeGroupId=pl.piotrsorobka.maven -DarchetypeArtifactId=javaee5-maven-archetype -DarchetypeVersion=1.0 -DgroupId=your.group.id -DartifactId=project-name
Deploy on Glassfish
Step 1:
Set environment variable GLASSFISH_HOME, pointing to your Glassfish installation folder. Alternatively, point <glassfishDirectory></glassfishDirectory> in your main pom.xml to your Glassfish installation folder.
Step 2:
Inside your project main folder run:
mvn clean install
and after:
mvn -f ear/pom.xml glassfish:deploy
If your Glassfish settings are default it will deploy the ear.
摘要: Spring3 and EJB Integration(I)EJB Client I used EJB client to call EJB stateless bean, I found it is waste time to lookup the stateless bean every time. So I tried to use spring to get singleton stub ...
閱讀全文