欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
JR 精品文章 - "面向切面(AOP)"與"面向對象(OOP)"(整理)
首先你要明確的一點(diǎn),AOP和OOP是兩種不同的認識事物的角度,并不是說(shuō)有了AOP就不要用OOP.AOP所關(guān)注的是傳統OOP不能優(yōu)雅解決的問(wèn)題.(程序員通常都是完美主義者,當解決某個(gè)問(wèn)題不優(yōu)雅的時(shí)候,那就意味著(zhù)不完美.)下面將就一個(gè)簡(jiǎn)單的例子來(lái)說(shuō)明他們到底如何的不同.
作為一個(gè)使用OOP多年的人來(lái)說(shuō),當我聽(tīng)說(shuō)AOP可以解決一些OOP一直都不能優(yōu)雅地解決的問(wèn)題時(shí),我覺(jué)得應該去探個(gè)究竟了.對兩種技術(shù)的比較最能給我們實(shí)際應用提供見(jiàn)解.這里我設計了一個(gè)例子:一個(gè)OOP應用,其中某些方面適合使用AOP.
本 文展示了一個(gè)簡(jiǎn)單的例子.一開(kāi)始介紹了問(wèn)題域,然后分別給出OOP與AOP的解決方案.后者使用了 JDK5.0,JUnit,和 AspectWerkz.最后說(shuō)明如何編寫(xiě)代碼.讀完本文后,我希望你能知道AOP到底是什么,解決什么樣的問(wèn)題.(由于作者在后面AOP的例子中使用了 Java5.0的批注(Annotation),建議讀者先有所了解. -- 譯者注).
問(wèn)題域描述
一個(gè)軟件公司雇傭一個(gè)程序員,指定給他一個(gè)業(yè)務(wù)部門(mén)并要求他隨時(shí)向經(jīng)理報告.當團隊成員完成他們的目標時(shí),經(jīng)理會(huì )給他們相應的獎金.公司所需要的方案必須能夠增加一個(gè)新的雇員并給當前的員工增加獎金.為了方便,我們用CSV文件存儲數據.
圖1 解決方案模型
類(lèi)Manager(經(jīng)理)繼承自類(lèi)Employee,包含一個(gè)額外的屬性,Managing Project.一個(gè)部門(mén)可能包含很多員工.多個(gè)部門(mén)構成了公司.暫不考慮公司這樣的一個(gè)類(lèi),因為它在問(wèn)題域之外.
解決方案設計
以下流程圖描述了解決方案設計.
圖2 對象之間的交互(增加一個(gè)新的員工,指派給他一個(gè)部門(mén)和經(jīng)理)
出于簡(jiǎn)單的考慮,本文只關(guān)注必需的細節.當然你也可以深入代碼得到你想要的其他信息.
[link]http://www.devx.com/assets/sourcecode/13172.zip[/link]
EmployeeServiceTestCase, 一個(gè)JUnit測試用例,模擬一個(gè)最終用戶(hù),創(chuàng )建新員工記錄,指派部門(mén)和經(jīng)理.它獲取所有可用的部門(mén)和經(jīng)理數據并顯示在圖形界面上.為了實(shí)例化域對象 BusinessUnit和Manager,獲得的記錄將傳遞給工廠(chǎng)類(lèi).之后,通過(guò)給EmployeeService傳遞一個(gè)引用來(lái)創(chuàng )建一個(gè) Employee對象.這個(gè)服務(wù)類(lèi)使用EmployeeFactory創(chuàng )建對象,并把這個(gè)對象傳給EmployeeRepository 來(lái)進(jìn)行持久化操 作.
應用程序中需要面向哪些"切面"
到目前為止,對模型和設計的討論還限于一個(gè)較抽象的層面.現在,我轉向這個(gè)應用的其他方面 - 這對理解AOP的價(jià)值至關(guān)重要.
操作所需的資源
public static Set findAllBusinessUnits() throws RepositoryException {
Set businessUnits = new HashSet();
try {
FileReader businessUnitFile = null;
BufferedReader bufferedBusinessUnitFile = null;
try {
businessUnitFile = new FileReader(FILE_NAME);
bufferedBusinessUnitFile = new BufferedReader(businessUnitFile);
String businessUnitRecord;
while((businessUnitRecord = bufferedBusinessUnitFile.readLine()) != null) {
BusinessUnit businessUnit = BusinessUnitFactory.createBusinessUnit(businessUnitRecord);
businessUnits.add(businessUnit);
}
} finally {
if(bufferedBusinessUnitFile != null) {
bufferedBusinessUnitFile.close();
}
if(businessUnitFile != null) {
businessUnitFile.close();
}
}
} catch(IOException ioe) {
logger.log(SEVERE, message, ioe);
throw new RepositoryException(message, ioe);
}
logger.log(INFO, "Manager Records returned:" + businessUnits.size());
return businessUnits;
}
上面的代碼通過(guò)FileReader和BUfferedReader來(lái)讀取CSV文件中的業(yè)務(wù)數據.
應用程序重復地從資源文件中取得數據然后在操作完成后釋放. 我們會(huì )發(fā)現:去掉程序的這兩個(gè)"切面"將提高代碼的可讀性并達到一個(gè)更好的設計,因為去掉這些"多余"的東西,剩下的代碼才是這個(gè)方法真正的精髓.這個(gè)方 法的作用是讀取業(yè)務(wù)單位數據.所以不應該也不需要去知道"如何獲取和釋放資源以及這個(gè)過(guò)程中出現的異常"這個(gè)"切面".同樣地,使用AOP處理異常也變得 不同.(后面將詳細介紹)
持久層
傳統的OOP使用倉庫類(lèi)(repository classes)來(lái)打理應用程序的持久層.即:
public class EmployeeRepository {
public static void createEmployee(Employee employee) throws RepositoryException {
//使用print writer把數據放入csv文件
}
public static 
String findEmployeeRecordById(String id) throws RepositoryException {
//使用file reader來(lái)獲得指定id的員工數據
}
public static Employee findEmployeeById(String id) throws RepositoryException {
//使用該方法獲取員工數據,Employee對象由工廠(chǎng)類(lèi)創(chuàng )建
}
public static void updateEmployee(Employee employee) {
//更新員工數據
}
}
類(lèi)EmployeeService 使用一個(gè)倉庫類(lèi)給應用中相關(guān)雇員提供服務(wù),在一個(gè)企業(yè)應用中,從域模型 (domain model)中去掉持久層代碼是一種設計上的改進(jìn).模型設計者和程序員就可以關(guān)注各自的業(yè)務(wù)邏輯和持久層處理.后面你將會(huì )看到如何通過(guò) AOP來(lái)達到這樣的效果.
日志
刪除用于調試的日志代碼將會(huì )極大地改進(jìn)代碼的可讀性.考慮下面的代碼片斷:
public Employee createEmployee(String name,
String contactNumber,
BusinessUnit businessUnit,
Manager manager)
throws EmployeeServiceException {
String id = createNewEmployeeId();
Employee employee =
EmployeeFactory.createEmployee(id, name, contactNumber, businessUnit, manager);
try {
EmployeeRepository.createEmployee(employee);
} catch(RepositoryException re) {
logger.log(SEVERE, message);
throw new EmployeeServiceException(message, re);
}
logger.log(INFO, "Created employee successfully:" + employee);
return employee;
}
上面的代碼里包含了一個(gè)致命錯誤和一個(gè)成功信息.輸出日志這一"切面"同樣可以移到業(yè)務(wù)模型外獨立實(shí)現.
異常處理
異 常處理的例子我這里不再贅述,但這節已經(jīng)通過(guò)上面的代碼討論了潛在的問(wèn)題.當你調用EmployeeRepository 對象的 createEmployee 方法時(shí),你可能會(huì )得到一個(gè)RepositoryException異常.傳統的解決方法是,在這個(gè)類(lèi)中處理.另一種方法 是,當RepositoryException 異常被拋出時(shí)createEmployee 方法返回null,catch塊中的其他邏輯可以在類(lèi)外處理 這一錯誤.
錯誤處理在不同的情況中也會(huì )不同.但是,通過(guò)AOP可以區分開(kāi)每種情況.
圖3
圖3中描述了AOP方法的設計以及在一個(gè)更抽象的層次上類(lèi)間的交互.你可以通過(guò)對比圖1和圖3來(lái)更好地理解AOP.
程 序的目的是通過(guò)BusinessUnit對象讀取CSV文件中的記錄然后 填入類(lèi)BusinessUnitService 中的map.使用AOP來(lái)填充 這個(gè)map有點(diǎn)類(lèi)似后門(mén)(backdoor)方法 -- 控制被委派給BusinessUnit 來(lái)讀取存儲介質(zhì)中的記錄.
AOP就是定 義一些切入點(diǎn)(pointcut)和處理方法(advice).一個(gè)"切入點(diǎn)"是源代碼中一個(gè)執行點(diǎn).前面的例子定義了一個(gè)"切入點(diǎn)" --  類(lèi) BusinessUnitService中的findBusinessUnits方法.一個(gè)"處理方法"顧名思義就是當執行到某個(gè)"切入點(diǎn)"時(shí)的一塊代 碼.類(lèi)BusinessUnitPersistentAspect 包括advice方法findAllBusinessUnits,該方法從存儲介質(zhì)中 載入數據,然后使用工廠(chǎng)類(lèi)創(chuàng )建BusinessUnit 對象.然后這個(gè)對象被加入map,map對象的引用通過(guò) BusinessUnitService 對象獲得."切入點(diǎn)"和"處理方法"組成了所謂的"切面(Aspect)"
為了讀取存儲介質(zhì)中的數據,OOP方法通過(guò)一個(gè)DAO類(lèi)來(lái)做.而AOP中,你只要定義一個(gè)"切入點(diǎn)"和相應的"處理方法"來(lái)讀取數據.AOP框架會(huì )以advice的形式注入代碼,既可以在執行期也可以在編譯期.
總 而言之,當類(lèi)BusinessUnitService 中的findAllBusinessUnits 方法被調用時(shí),AOP框架會(huì )在"切入點(diǎn)"處注入處 理方法,通過(guò)BusinessUnit 對象預先讀取數據來(lái)填充map對象.這樣,持久層方面的代碼就可以移到業(yè)務(wù)代碼之外了.
新方法里的"切面"
本節討論如何用AOP為應用程序的各個(gè)"切面"建模
操作資源
類(lèi)BusinessUnitPersistenceAspect 的持久方法使用了一個(gè)buffered reader.你甚至可以定義"切面"的"切面",但為了簡(jiǎn)單,這里只關(guān)注類(lèi)的查找方法.
@Aspect("perJVM")
public class BufferedFileReaderAspect {
@Expression("execution(* org.javatechnocrats.aop.withaop.aspects.BusinessUnitPersistenceAspect.find*(..))")
Pointcut businessUnitPersistenceAspect;
// 其他"切入點(diǎn)"定義
@Expression("businessUnitPersistenceAspect ||
employeePersistenceAspect ||
managerPersistenceAspect")
Pointcut allPersistencePointcuts;
private Map<
ClassString> fileNames;
public BufferedFileReaderAspect() {
fileNames = new HashMap<ClassString>();
fillFileNames();
}
@Before("allPersistencePointcuts")
public void assignReader(JoinPoint joinPoint) throws Throwable {
Object callee = joinPoint.getCallee();
IBufferedFileReaderConsumable bufReaderConsumable = (IBufferedFileReaderConsumable)callee;
Class persistenceClass = callee.getClass();
String fileName = fileNames.get(persistenceClass);
FileReader fileReader = new FileReader(fileName);
BufferedReader bufferedReader = new BufferedReader(fileReader);
bufReaderConsumable.setBufferedReader(bufferedReader);
}
@AfterFinally("allPersistencePointcuts")
public void releaseReader(JoinPoint joinPoint) throws Throwable {
//釋放buffered reader等資源
}
//其他方法
}
上面的代碼試圖為每一個(gè)方法創(chuàng )建"切入點(diǎn)"-- 所有以find開(kāi)頭的方法.無(wú)論何時(shí)這些方法被調用,assignReader方法都會(huì )被提前執行.這里它獲取被調用的類(lèi)實(shí)例然后設置新建的buffered reader.
同樣地,在releaseReader 方法里,代碼會(huì )預先關(guān)閉buffered reader集合.本節只解釋@before和@
AfterFinally 這兩個(gè)"切入點(diǎn)".(以J2SE 5.0的標記定義).另外,你也可以在方面定義的xml文件中聲明他們.你可以查看例程源代碼中的aop.xml文件.
下載
持久化
前 面提到,OOP方法使用BusinessUnit 來(lái)為應用的持久層填充Map.在下面的高亮代碼中(@before一行,以及while循環(huán)代碼 -  譯者注),當BusinessUnitService 中的方法findAllBusinessUnits 被調用時(shí)"處理方法 "findAllBusinessUnits 也將被調用.
@Aspect("perJVM")
public class BusinessUnitPersistenceAspect implements IBufferedFileReaderConsumable {
private BufferedReader buffFileReader;
@Before("execution(Collection org.javatechnocrats.aop.withaop.BusinessUnitService.findAllBusinessUnits())")
public void findAllBusinessUnits(JoinPoint joinPoint) throws Throwable {
Map<String, BusinessUnit> businessUnits =
((BusinessUnitService)joinPoint.getThis()).getBusinessUnits();
String businessUnitRecord;
while((businessUnitRecord = buffFileReader.readLine()) != null) {
BusinessUnit businessUnit = BusinessUnitFactory.createBusinessUnit(businessUnitRecord);
businessUnits.put(businessUnit.getId(), businessUnit);
}
}
public void setBufferedReader(BufferedReader buffFileReader) {
this.buffFileReader = buffFileReader;
}
public BufferedReader getBufferedReader() {
return this.buffFileReader;
}
}
"處理方法"從數據存儲中讀取記錄,使用工廠(chǎng)類(lèi)創(chuàng )建一個(gè)BusinessUnit實(shí)例.然后這個(gè)實(shí)例被加入到Map.該Map掌管程序的所有持久化"切面".
日志
本文中的例子沒(méi)有包含一個(gè)完整的日志AOP解決方案.但是,它為java.lang.Object類(lèi)的toString方法定義了一個(gè)"切入點(diǎn)"來(lái)獲取類(lèi)的調試信息.因此,域中的類(lèi)不需要實(shí)現toString方法.通??赡苣憧赡苄枰獮槊恳粋€(gè)類(lèi)都要實(shí)現這個(gè)方法.
@Aspect("perJVM")
public class LoggingAspect {
@Around("execution(String org.javatechnocrats.aop.withaop..*.toString())")
public 
Object toStringAdvice(JoinPoint joinPoint) throws Throwable {
String toString = (String)joinPoint.proceed();
Object target = joinPoint.getThis();
Field fields[] = target.getClass().getDeclaredFields();
List members = new ArrayList(fields.length + 1);
members.add(toString);
for(Field field : fields) {
field.setAccessible(true);
Object member = field.get(target);
members.add(field.getName() + "=" + member);
}
return members.toString();
}
你也可以用這個(gè)樣例代碼完成錯誤處理"切面".
深入源代碼
為了理解樣例需求的OOP設計,請參看源代碼并思考以下幾個(gè)問(wèn)題: 下載
* 首先分析oldway包中EmployeeServiceTestCase 類(lèi)中的代碼
*查看testEmployeeCredit 方法
*搞懂業(yè)務(wù)類(lèi)Employee和BusinessUnit
*學(xué)習 service,repository和factory概念.這些是業(yè)務(wù)驅動(dòng)設計的主要概念.
*更深入地理解oldway包中的service,repository和factory類(lèi)
而AOP地理解則應該是:
*分析newway包中EmployeeServiceTestCase 類(lèi)
*查看service,repository和factory類(lèi),基本和前一種差不多.只是你要讓"處理方法"截獲程序的執行流程.
*研究aspect類(lèi)學(xué)習"切入點(diǎn)"的定義
要執行程序,你需要做的工作:
* 下載AspectWerkz 2.0 http://aspectwerkz.codehaus.org/
*設置以下的環(huán)境變量:
set JAVA_HOME=c:\Program Files\Java\jdk1.5.0
set ASPECTWERKZ_HOME=C:\aw_2_0_2
set PATH=%PATH%;%ASPECTWERKZ_HOME%\bin
set CLASSPATH=
C:\aw_2_0_2\lib\aspectwerkz-2.0.RC2.jar;C:\aw_2_0_2\lib\aspectwerkz-jdk5-2.0.RC2.jar; classes;C:\ junit\3.8.1\resources\lib\junit.jar
*解壓縮源代碼和其他文件
*編譯Java文件,但不要編譯測試用例否則你調試時(shí)會(huì )遇到一個(gè)錯誤.
*進(jìn)行離線(xiàn)調試.假設你把文件解壓縮到c:\aop ,類(lèi)文件解壓到c:\aop\classes,在c:\aop目錄下執行以下命令:
%ASPECTWERKZ_HOME%\bin\aspectwerkz -offline etc/aop.xml -cp classes classes
*AOP框架會(huì )修改類(lèi)來(lái)注入必要的字節碼
*編譯測試用例,使用JUnit運行它.
后記
當你完成了上面的這些工作,你應該有以下的領(lǐng)悟:
*程序中的交叉關(guān)聯(lián)
*關(guān)于A(yíng)OP中深入源代碼
為了理解樣例需求的OOP設計,請參看源代碼并思考以下幾個(gè)問(wèn)題: 下載
* 首先分析oldway包中EmployeeServiceTestCase 類(lèi)中的代碼
*查看testEmployeeCredit 方法
*搞懂業(yè)務(wù)類(lèi)Employee和BusinessUnit
*學(xué)習 service,repository和factory概念.這些是業(yè)務(wù)驅動(dòng)設計的主要概念.
*更深入地理解oldway包中的service,repository和factory類(lèi)
而AOP地理解則應該是:
*分析newway包中EmployeeServiceTestCase 類(lèi)
*查看service,repository和factory類(lèi),基本和前一種差不多.只是你要讓advice截取程序的流程.
*研究aspect類(lèi)學(xué)習point cut的定義
要執行程序,你需要做的工作:
* 下載AspectWerkz 2.0 http://aspectwerkz.codehaus.org/
*設置以下的環(huán)境變量:
set JAVA_HOME=c:\Program Files\Java\jdk1.5.0
set ASPECTWERKZ_HOME=C:\aw_2_0_2
set PATH=%PATH%;%ASPECTWERKZ_HOME%\bin
set CLASSPATH=
C:\aw_2_0_2\lib\aspectwerkz-2.0.RC2.jar;C:\aw_2_0_2\lib\aspectwerkz-jdk5-2.0.RC2.jar; classes;C:\ junit\3.8.1\resources\lib\junit.jar
*解壓縮源代碼和其他文件
*編譯Java文件,但不要編譯測試用例否則你調試時(shí)會(huì )遇到一個(gè)錯誤.
*進(jìn)行離線(xiàn)調試.假設你把文件解壓縮到c:\aop ,類(lèi)文件解壓到c:\aop\classes,在c:\aop目錄下執行以下命令:
%ASPECTWERKZ_HOME%\bin\aspectwerkz -offline etc/aop.xml -cp classes classes
*AOP框架會(huì )修改類(lèi)來(lái)注入必要的字節碼
*編譯測試用例,使用JUnit運行它.
后記
當你完成了上面的這些工作,你應該有以下的領(lǐng)悟:
*程序中的交叉關(guān)聯(lián)
*關(guān)于A(yíng)OP中"切面"的含義
*如何用AOP來(lái)把程序業(yè)務(wù)層中的交叉關(guān)聯(lián)分離出來(lái),使用"切入點(diǎn)"和"處理方法"
*OOP和AOP時(shí)在程序控制流上的不同
從本文你應該也得到一種看待實(shí)際開(kāi)發(fā)的新視角.你應該有信心使用AOP來(lái)改進(jìn)項目中的設計,建模,提高代碼的重用性.至少,你可以開(kāi)始使用AOP來(lái)處理日志,錯誤和持久化.
個(gè)人覺(jué)得,AOP的學(xué)習曲線(xiàn)相對較陡,尤其在理解定義"切入點(diǎn)"的句法時(shí).理想的情況是,使用OOP來(lái)設計業(yè)務(wù)模型,使用AOP把業(yè)務(wù)模型中的交叉關(guān)聯(lián)移出,從而使代碼簡(jiǎn)潔并提高可讀性.
AOP的一個(gè)缺點(diǎn)是會(huì )使調試變得困難,因為不同于OOP,程序流變的復雜了,交互是由編譯期或執行期決定.我準備將來(lái)做一些自動(dòng)化工具來(lái)解決這個(gè)問(wèn)題.
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
Spring:(二) -- 春風(fēng)拂面之 核心 AOP
Spring AOP學(xué)習4 - 使用基于A(yíng)spectj風(fēng)格配置AOP-3 配置詳解
【第六章】 AOP 之 6.3 基于Schema的AOP ——跟我學(xué)spring3
我的控制反轉,依賴(lài)注入和面向切面編程的理解
.NET中的AOP介紹
InfoQ: Spring 2.0的新特性和應用實(shí)踐
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久