***注:非入门者读***
Spring框架中成功吸引人的一点就是容器事务的管理提供了一个轻量级的容器事务处理针对的对象是普通的java类使用Spring事务管理的话你可以按照自己的业务把一些相关的方法纳入其事务管理里面这就避免了程序员在处理事务的过程中繁琐的工作同时这些也是ejbX规范里面吸引人的一点这在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中提供了种处理切入类型:aroundbeforeafterintroduction顾名思义
)around是针对具体的某个切入点的方法(比如现在有个OrderBook方法around的切入类型是就这个方法的内部调用是通过java的元数据在运行时通过Methodinvoke来调用具有返回值当发生意外的时候会终止记住的一点是返回值);
)before是在方法调用前调用(在OrderBook方法前调用但是没有返回值同时在通常意外情况下会继续运行下一步方法记住的一点是没有返回值);
)after和before刚好相反没有什么特别的地方
)introduction是一个更加特殊的但功能更加强大的切入类型比如(你现在有Book对象Computer对象还有几十个这种业务对象现在你希望在每个这样的对象中都加入一个记录最后修改的时间但是你又不希望对每个类都进行修改因为太麻烦了同时更重要的一点破坏了对象的完整性说不定你以后又不需要这个时间数据了呢这时怎么办呢?Spring AOP就为你专门实现这种思想提供了一个切入处理那就是introductionintroduction可以为你动态加入某些方法这样可以在运行时强制转换这些对象进行插入时间数据的动作更深的内幕就是C++虚函数中的vtable思想)不过这种动态是以性能作为代价的使用之前要慎重考虑这里我们谈的是技术所以就认为他是必需的
好现在我们就拿第四种来进行举例说明Spring AOP的强大之处:
)假设创建了一个BookService接口及其实现方法(你自己的业务对象):
//$ID:BookServicejava Created: by Kerluse Benn
package comosirisspringaop;
public interface BookService {
public String OrderComputerMagazine(String userNameString bookName);
public String OrderBook(String userNameString bookName);
}
//$ID:BookServiceImpljava Created: by Kerluse Benn
package comosirisspringaop;
public class BookServiceImpl implements BookService{
public String OrderBook(String nameString 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:IAuditablejava Created: by Kerluse Benn
package comosirisspringaopadvicesintruduction;
import javautilDate;
public interface IAuditable {
void setLastModifiedDate(Date date);
Date getLastModifiedDate();
}
)因为我们使用的切入类型是introductionSpring AOP为我们提供了一个描述这种类型的接口IntroductionInterceptor所以我们的切入实现处理也需要实现这个接口:
//$ID:AuditableMixinjava Created: by Kerluse Benn
package comosirisspringaopadvicesintruduction;
import javautilDate;
import orgaopallianceinterceptMethodInvocation;
import orgspringframeworkaopIntroductionInterceptor;
public class AuditableMixin implements IAuditableIntroductionInterceptor{
private Date lastModifiedDate;
public Object invoke(MethodInvocation m) throws Throwable {
// TODO Add your codes here
if(implementsInterface(mgetMethod()getDeclaringClass())){
return mgetMethod()invoke(thismgetArguments());
//invoke introduced mthodhere is IAuditable
}else{
return mproceed(); //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 clsisAssignableFrom(IAuditableclass);
}
}
)ok现在业务对象BookService类有了自己希望添加的处理也有了IAuditable那就剩下使用Spring AOP框架的问题了配置beanxml文件:
<?xml version= encoding=UTF?>
<!DOCTYPE beans PUBLIC //SPRING//DTD BEAN//EN beansdtd>
<beans>
<! Beans >
<bean id=BookServiceTarget class=comosirisspringaopBookServiceImpl singleton=false/>
<! introduction advice >
<bean id=AuditableMixin class=comosirisspringaopadvicesintruductionAuditableMixin singleton=false/>
<! Introduction advisor >
<bean id=AuditableAdvisor class=orgspringframeworkaopsupportDefaultIntroductionAdvisor
singleton=false>
<constructorarg>
<ref bean=AuditableMixin/>
</constructorarg>
</bean>
<bean id=BookService class=orgspringframeworkaopframeworkProxyFactoryBean>
<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>comosirisspringaopadvicesintruductionIAuditable</value>
</property>
<property name=interceptorNames>
<list>
<value>AuditableAdvisor</value>
</list>
</property>
</bean>
</beans>
以上就是配置文件现在我们假设使用业务对象如下这里是一个简单测试类:
//$ID:MainAppjava Created: by Kerluse Benn
package comosirisspringaop;
import javautilDate;
import orgspringframeworkbeansfactoryBeanFactory;
import orgspringframeworkbeansfactoryxmlXmlBeanFactory;
import orgreioFileSystemResource;
import comosirisspringaopadvicesintruductionIAuditable;
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(beanxml));
BookService bookService=(BookService)factorygetBean(BookService);
IAuditable auditable=(IAuditable)bookService;
Systemoutprint(bookServiceOrderBook(Kerluse BennProfessional C#));
auditablesetLastModifiedDate(new Date());
Systemoutprintln( 订购时间为+auditablegetLastModifiedDate());
Threadsleep();
Systemoutprint(bookServiceOrderBook(Kerluse BennExpert jee oneonone));
auditablesetLastModifiedDate(new Date());
System