***注:非入門者讀***
Spring框架中成功吸引人的一點就是容器事務的管理
提供了一個輕量級的容器事務處理
針對的對象是普通的java類
使用Spring事務管理的話
你可以按照自己的業務把一些相關的方法納入其事務管理裡面
這就避免了程序員在處理事務的過程中繁瑣的工作
同時這些也是ejb
X規范裡面吸引人的一點
這在spring裡面都很好的提供
雖然在跨容器的事務管理
spring裡面並沒有提供
但是對於一般的web程序來說
也不需要僅僅為了那些功能而不得不使用ejb
不過
最近jboss的嵌入式的ejb容器也可以做的更小了
也是開源中的選擇之一
無論技術是怎樣發展的
當前
我們先來研究其中AOP實現的方法
事實上
Spring中的事務處理是通過AOP思想來實現的
Spring AOP與Aspect J和JBoss具有很大的不同
首先
使用Spring AOP框架的用戶要記住的一點是
Spring AOP針對的是方法層次上的實現
而其他兩者對字段也提供了支持
說到Spring AOP的內幕
其實也不難
對於有接口的類
使用的是Java內部類提供的Proxy;而對於那些不實現接口的類
使用的是cglib庫
動態創建一個子類來實現
在Spring AOP中提供了
種處理切入類型:around
before
after
introduction
顧名思義
)around是針對具體的某個切入點的方法(比如
現在有個OrderBook方法
around的切入類型是就這個方法的內部調用
是通過java的元數據
在運行時通過Method
invoke來調用
具有返回值
當發生意外的時候會終止
記住的一點是
返回值
);
)before是在方法調用前調用(在OrderBook方法前調用
但是沒有返回值
同時在通常意外情況下
會繼續運行下一步方法
記住的一點是沒有返回值);
)after和before剛好相反
沒有什麼特別的地方
)introduction是一個更加特殊的
但功能更加強大的切入類型
比如(你現在有Book對象
Computer對象
還有幾十個這種業務對象
現在你希望在每個這樣的對象中都加入一個記錄最後修改的時間
但是你又不希望對每個類都進行修改
因為太麻煩了
同時更重要的一點
破壞了對象的完整性
說不定你以後又不需要這個時間數據了呢
這時怎麼辦呢?Spring AOP就為你專門實現這種思想提供了一個切入處理
那就是introduction
introduction可以為你動態加入某些方法
這樣可以在運行時
強制轉換這些對象
進行插入時間數據的動作
更深的內幕就是C++虛函數中的vtable思想)
不過這種動態是以性能作為代價的
使用之前要慎重考慮
這裡我們談的是技術
所以就認為他是必需的
好
現在我們就拿第四種來進行舉例說明Spring AOP的強大之處:
)假設創建了一個BookService接口及其實現方法(你自己的業務對象):
//$ID:BookService
java Created:
by Kerluse Benn
package com
osiris
springaop;
public interface BookService {
public String OrderComputerMagazine(String userName
String bookName);
public String OrderBook(String userName
String bookName);
}
//$ID:BookServiceImpl
java Created:
by Kerluse Benn
package com
osiris
springaop;
public class BookServiceImpl implements BookService{
public String OrderBook(String name
String bookName) {
// TODO Add your codes here
String result=null;
result=
訂購
+bookName+
成功
;
return result;
}
public String OrderComputerMagazine(String userName
String bookName) {
// TODO Add your codes here
String result=null;
result=
訂購
+bookName+
成功
;
return result;
}
}
)事實上你還有很多這樣的對象
現在我們希望在每個對象中添加我們的功能最後修改的時間
功能如下:
//$ID:IAuditable
java Created:
by Kerluse Benn
package com
osiris
springaop
advices
intruduction;
import java
util
Date;
public interface IAuditable {
void setLastModifiedDate(Date date);
Date getLastModifiedDate();
}
)因為我們使用的切入類型是introduction
Spring AOP為我們提供了一個描述這種類型的接口IntroductionInterceptor
所以我們的切入實現處理
也需要實現這個接口:
//$ID:AuditableMixin
java Created:
by Kerluse Benn
package com
osiris
springaop
advices
intruduction;
import java
util
Date;
import org
aopalliance
intercept
MethodInvocation;
import org
springframework
aop
IntroductionInterceptor;
public class AuditableMixin implements IAuditable
IntroductionInterceptor{
private Date lastModifiedDate;
public Object invoke(MethodInvocation m) throws Throwable {
// TODO Add your codes here
if(implementsInterface(m
getMethod()
getDeclaringClass())){
return m
getMethod()
invoke(this
m
getArguments());
//invoke introduced mthod
here is IAuditable
}else{
return m
proceed(); //delegate other method
}
}
public Date getLastModifiedDate() {
// TODO Add your codes here
return lastModifiedDate;
}
public void setLastModifiedDate(Date date) {
// TODO Add your codes here
lastModifiedDate=date;
}
public boolean implementsInterface(Class cls) {
// TODO Add your codes here
return cls
isAssignableFrom(IAuditable
class);
}
}
)ok
現在業務對象BookService類有了
自己希望添加的處理也有了IAuditable
那就剩下使用Spring AOP框架的問題了
配置bean
xml文件:
<?xml version=
encoding=
UTF
?>
<!DOCTYPE beans PUBLIC
//SPRING//DTD BEAN//EN
beans
dtd
>
<beans>
<!
Beans
>
<bean id=
BookServiceTarget
class=
com
osiris
springaop
BookServiceImpl
singleton=
false
/>
<!
introduction advice
>
<bean id=
AuditableMixin
class=
com
osiris
springaop
advices
intruduction
AuditableMixin
singleton=
false
/>
<!
Introduction advisor
>
<bean id=
AuditableAdvisor
class=
org
springframework
aop
support
DefaultIntroductionAdvisor
singleton=
false
>
<constructor
arg>
<ref bean=
AuditableMixin
/>
</constructor
arg>
</bean>
<bean id=
BookService
class=
org
springframework
aop
framework
ProxyFactoryBean
>
<property name=
target
>
<ref bean=
BookServiceTarget
/>
</property>
<property name=
singleton
>
<value>false</value>
</property>
<!
force to use cglib
>
<property name=
proxyTargetClass
>
<value>true</value>
</property>
<!
introduction methods
>
<property name=
proxyInterfaces
>
<value>com
osiris
springaop
advices
intruduction
IAuditable</value>
</property>
<property name=
interceptorNames
>
<list>
<value>AuditableAdvisor</value>
</list>
</property>
</bean>
</beans>
以上就是配置文件
現在我們假設使用業務對象如下
這裡是一個簡單測試類:
//$ID:MainApp
java Created:
by Kerluse Benn
package com
osiris
springaop;
import java
util
Date;
import org
springframework
beans
factory
BeanFactory;
import org
springframework
beans
factory
xml
XmlBeanFactory;
import orgre
io
FileSystemResource;
import com
osiris
springaop
advices
intruduction
IAuditable;
public class MainApp {
/**
* @param args
* @author Kerluse Benn
*/
public static void main(String[] args) throws Exception{
// TODO Add your codes here
BeanFactory factory=new XmlBeanFactory(new FileSystemResource(
bean
xml
));
BookService bookService=(BookService)factory
getBean(
BookService
);
IAuditable auditable=(IAuditable)bookService;
System
out
print(bookService
OrderBook(
Kerluse Benn
Professional C#
));
auditable
setLastModifiedDate(new Date());
System
out
println(
訂購時間為
+auditable
getLastModifiedDate());
Thread
sleep(
);
System
out
print(bookService
OrderBook(
Kerluse Benn
Expert j
ee one
on
one
));
auditable
setLastModifiedDate(new Date());
System
From:http://tw.wingwit.com/Article/program/Java/ky/201311/28652.html