Spring学习笔记(九)-----Spring in Action
ThrowsAdvice让你定义在异常发生时该有什么动作。ThrowsAdvice是一个标示接口,它没有定义任何必须实现的方法。但
是,实现这个接口的类必须至少有一个如下形式的方法:
void afterThrowing(Throwable throwable);
void afterThrowing(Method method,Object[] args,Object target,Throwable throwable);
第一个方法只接受一个参数:需要抛出的异常。第二个方法接受异常、被调用的方法、参数以及目标对象。除非需要这些外加参数,你只要实现单参数方法就可以了。你的ThrowsAdvice要处理的异常取决于你的方法定义的异常类型。
你也可以在一个类中实现多个afterThrowing方法。代码如下:
package
com.wyq.spring.base.aopinstance;
import org.springframework.aop.ThrowsAdvice;
/**
* @author 作者
* @version 创建时间:2009-11-5 下午05:39:17
* 类说明
*/
public class KwikEMartExceptionAdvice implements ThrowsAdvice {
/*
* 根据抛出异常的类型恰当方法将被调用。注意,除了捕获和处理异常以外,这些方法都为应用添加了新的行为。
* 这是因为你无法做到这一点。代理对象捕获异常并且调用合适的ThrowsAdvice方法,如果有的话。ThrowsAdvice
* 被执行后,原来的异常继续被抛出,并且向其他异常一样被传播出去。
*/
public void afterThrowing(NoMoreSquisheesException e){
orderMoreSquishees();
}
public void afterThrowing(CustomerIsBrokeException e){
showCustomerAtmMachine();
}
}
import org.springframework.aop.ThrowsAdvice;
/**
* @author 作者
* @version 创建时间:2009-11-5 下午05:39:17
* 类说明
*/
public class KwikEMartExceptionAdvice implements ThrowsAdvice {
/*
* 根据抛出异常的类型恰当方法将被调用。注意,除了捕获和处理异常以外,这些方法都为应用添加了新的行为。
* 这是因为你无法做到这一点。代理对象捕获异常并且调用合适的ThrowsAdvice方法,如果有的话。ThrowsAdvice
* 被执行后,原来的异常继续被抛出,并且向其他异常一样被传播出去。
*/
public void afterThrowing(NoMoreSquisheesException e){
orderMoreSquishees();
}
public void afterThrowing(CustomerIsBrokeException e){
showCustomerAtmMachine();
}
}
<?
xml version="1.0" encoding="UTF-8"
?>
<! DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd" >
< beans >
<!-- 创建代理目标对象 -->
< bean id ="kwikEMartTarget" class ="com.springinaction.chapter03.store.ApuKwikEMart" ></ bean >
<!-- 创建通知 -->
< bean id ="welcomeAdvice" class ="com.springinaction.chapter03.store.WelcomeAdvice" ></ bean >
<!-- 创建代理对象 -->
< bean id ="kwikEMart" class ="org.springframework.aop.framework.ProxyFactoryBean" >
<!-- 代理类实现的接口 -->
< property name ="proxyInterfaces" >
< value > com.springinaction.chaper03.store.kwikEMart </ value >
</ property >
<!-- 要织入的通知 -->
< property name ="interceptorNames" >
< list >
< value > welcomeAdvice </ value >
</ list >
</ property >
<!-- 要代理的目标对象 -->
< property name ="target" >
< ref bean ="kwikEMartTarget" />
</ property >
</ bean >
</ beans >
<! DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd" >
< beans >
<!-- 创建代理目标对象 -->
< bean id ="kwikEMartTarget" class ="com.springinaction.chapter03.store.ApuKwikEMart" ></ bean >
<!-- 创建通知 -->
< bean id ="welcomeAdvice" class ="com.springinaction.chapter03.store.WelcomeAdvice" ></ bean >
<!-- 创建代理对象 -->
< bean id ="kwikEMart" class ="org.springframework.aop.framework.ProxyFactoryBean" >
<!-- 代理类实现的接口 -->
< property name ="proxyInterfaces" >
< value > com.springinaction.chaper03.store.kwikEMart </ value >
</ property >
<!-- 要织入的通知 -->
< property name ="interceptorNames" >
< list >
< value > welcomeAdvice </ value >
</ list >
</ property >
<!-- 要代理的目标对象 -->
< property name ="target" >
< ref bean ="kwikEMartTarget" />
</ property >
</ bean >
</ beans >
引入通知:引入通知与前面的通知类型有点不同。其他类型的通知是在目标对象的方法被调用的周围织入。引入通知给目标对象添加新的方法。
切入点决定了一个特定类的特定方法是否满足一条特定规则。如果一个方法确实符合,通知就应用到该方法上。Spring的切入点可以让我们以一种灵活的方式定义在什么地方将通知织入到我们的类中。
Spring根据需要织入通知的类和方法来定义切入点。Spring的切入点框架的核心接口自然史pointcut.
public interface Pointcut{
ClassFilter getClassFilter();//这个接口决定了一个类是否复合通知的要求
MethodMatcher getMethodMatcher();//方法过滤
}
大多数切面是由定义切面行为的通知和定义切面在什么地方执行的切入点组合而成的。Spring认识到这一点,提供了Advisor,
它把通知和切入点组合到一个对象中。
public interface PointcutAdvisor{
Pointcut getPointcut();
Advice getAdvice();
}
大多数Spring自带的切入点都有一个对应的PointcutAdvisor.这样方便你在一个地方定义切入点和通知。
<?
xml version="1.0" encoding="UTF-8"
?>
<! DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd" >
< beans >
<!-- 创建代理目标对象 -->
< bean id ="maidServiceTarget" class ="com.springinaction.chapter03.cleaning.MaidServiceImpl" ></ bean >
<!-- 创建通知 -->
< bean id ="frequentCustomerAdvice" class ="com.springinaction.chapter03.cleaning.FrequentCustomerAdvicer" ></ bean >
<!-- 定义切入点
使用Namedmethodmatcher可以很清楚的指明哪些方法需要使用通知。然而,对于大型应用系统,把每个需要通知的方法都列出来
会使配置文件显得非常冗长。使用通配符可以帮助我们解决这个问题。
Spring的RegexpMethodPointcut让你利用正则表达式的力量来定义切入点。这样你可以使用Perl样式的正则表达式来定义模式,
以得到你想要的方法。
.匹配任何单个字符
+匹配前一个字符一次或多次
*匹配前一个字符0次或多次
\匹配任何正则表达式符号
-->
< bean id ="frequentCustomerPointcutAdvisor" class ="org.springframework.aop.support.NameMatchMethodPointcutAdvisor" >
< property name ="mappedName" >
< value > order* </ value >
</ property >
< property name ="advice" >
< ref bean ="frequentCustomerAdvice" />
</ property >
</ bean >
<!-- 如果你想匹配所有setXxx方法,我们需要使用.*set*.模板(第一个通配符匹配任何类名) -->
< bean id ="queryPointcutAdvisor" class ="org.springframework.aop.support.RegexpMethodPointcutAdvisor" >
< property name ="pattern" >
< value > .*get.+By.+ </ value >
</ property >
< property name ="advice" >
< ref bean ="frequentCustomerAdvice" />
</ property >
</ bean >
<!-- 定义代理对象 -->
< bean id ="maidService" class ="org.springframework.aop.framework.ProxyFactoryBean" >
< property name ="proxyInterfaces" >
< value > com.springinaction.chapter03.cleaning.MaidService </ value >
</ property >
< property name ="interceptorNames" >
< list >
< value > frequentCustomerAdvisor </ value >
</ list >
</ property >
< property name ="target" >
< ref bean ="maidServiceTarget" />
</ property >
</ bean >
</ beans >
<! DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd" >
< beans >
<!-- 创建代理目标对象 -->
< bean id ="maidServiceTarget" class ="com.springinaction.chapter03.cleaning.MaidServiceImpl" ></ bean >
<!-- 创建通知 -->
< bean id ="frequentCustomerAdvice" class ="com.springinaction.chapter03.cleaning.FrequentCustomerAdvicer" ></ bean >
<!-- 定义切入点
使用Namedmethodmatcher可以很清楚的指明哪些方法需要使用通知。然而,对于大型应用系统,把每个需要通知的方法都列出来
会使配置文件显得非常冗长。使用通配符可以帮助我们解决这个问题。
Spring的RegexpMethodPointcut让你利用正则表达式的力量来定义切入点。这样你可以使用Perl样式的正则表达式来定义模式,
以得到你想要的方法。
.匹配任何单个字符
+匹配前一个字符一次或多次
*匹配前一个字符0次或多次
\匹配任何正则表达式符号
-->
< bean id ="frequentCustomerPointcutAdvisor" class ="org.springframework.aop.support.NameMatchMethodPointcutAdvisor" >
< property name ="mappedName" >
< value > order* </ value >
</ property >
< property name ="advice" >
< ref bean ="frequentCustomerAdvice" />
</ property >
</ bean >
<!-- 如果你想匹配所有setXxx方法,我们需要使用.*set*.模板(第一个通配符匹配任何类名) -->
< bean id ="queryPointcutAdvisor" class ="org.springframework.aop.support.RegexpMethodPointcutAdvisor" >
< property name ="pattern" >
< value > .*get.+By.+ </ value >
</ property >
< property name ="advice" >
< ref bean ="frequentCustomerAdvice" />
</ property >
</ bean >
<!-- 定义代理对象 -->
< bean id ="maidService" class ="org.springframework.aop.framework.ProxyFactoryBean" >
< property name ="proxyInterfaces" >
< value > com.springinaction.chapter03.cleaning.MaidService </ value >
</ property >
< property name ="interceptorNames" >
< list >
< value > frequentCustomerAdvisor </ value >
</ list >
</ property >
< property name ="target" >
< ref bean ="maidServiceTarget" />
</ property >
</ bean >
</ beans >