Spring --- AOP IV

Spring AOP APIs
一)一个最简单的例子
public interface MessageSender { 
void send(String message);
}
public class HttpMessageSender implements MessageSender {
public void send(String message) {
System.out.println("Send Message[" + message + "] by http.");
}
}

public class LogBeforeAdvice implements MethodAdvice {
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("Log before " + method + " by LogBeforeAdvice.");
}
}

<bean id="messageSenderImpl" class="com.savage.aop.HttpMessageSender"></bean>
<bean id="logBeforeAdvice" class="com.savage.aop.LogBeforeAdvice"></bean>

<bean id="messageSender" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces" value="com.savage.aop.MessageSender"/>
<property name="target" ref="messageSenderImpl"/>
<property name="interceptorNames">
<list>
<value>logBeforeAdvice</value>
</list>
</property>
</bean>


这样我们就为MessageSender对象指定了一个Before Advice。
在这里,我们分别定义了一个HttpMessageSender的bean(messageSenderImpl),一个Before Advice的bean(logBeforeAdvice)和一个org.springframework.aop.framework.ProxyFactoryBean的bean (messageSender)。
FactoryBean或ApplicationContext将使用ProxyFactoryBean来建立代理对象,在这里就是建立messageSenderImpl的代理对象。在ProxyFactoryBean的定义中,proxyInterfaces属性指定了要代理的接口;target指定了要建立代理的目标对象;interceptorNames则指定了应用与指定接口上的Advices对象列表,spring将根据列表中定义的顺序在执行目标对象的方法前、后执行。

二)AOP的Adivce
先说说adivce,可以分为Per-class和Per-instance。
[b] Per-class[/b]是指类级别的adivce,及该类的每个实例都相同的切面。切面不会为目标对象保存任何状态或者添加新的特性。 Before Advice,Throws Advice,After Returning Advice,Around Advice都属于这个类。
[b]Per-instance[/b]是指为每个实例各自保存状态或者添加新特性的advice。Introduction就属于这一类。
Before Advice对应的接口是MethodBeforeAdvice
Throws Advice对应的接口是ThrowsAdvice
After Returning Advice对应的接口是AfterReturningAdvice
Around Advice对应的接口是MethodInterceptor
Introduction对应的接口是IntroductionInterceptor
不同的Adivce的使用方式都基本一致。参照样例在interceptorNames属性中加入需要使用的一个或多个Adivce的bean id即可。

三)AOP的Pointcut
Pointcut的核心接口是:
public interface Pointcut {
ClassFilter getClassFilter();
MethodMatcher getMethodMatcher();
}

其中,ClassFilter和MethodMather分别用于匹配将被执行织入操作的对象以及相应的方法。
先说说ClassFilter。它的作用是对jointpoint处的对象进行class级别的匹配。
public interface ClassFilter {
boolean matches(Class clazz);
}

当织入的目标对象的class类型与pointcut所规定的类型相符时,matches方法将返回true。否则将返回false,即意味着不会对这个类型进行织入操作。
再来说说MethodMatcher。
 public interface MethodMatcher {
boolean matches(Method m, Class targetClass);
boolean isRuntime();
boolean matches(Method m, Class targetClass, Object[] args);
}

MethodMatcher定义了2个matches的方法。在对对象方法进行具体拦截的时候,可以忽略每次方法执行的时候调用者传入的参数,也可以每次都检查这些方法调用参数,以强化拦截条件。
1)前者我们调用matches(Method m, Class targetClass); 而后isRuntime();返回false,表示检查结束。这种类型的MethodMatcher称为静态方法匹配。
2)后者在isRuntime();返回true时进而调用matches(Method m, Class targetClass, Object[] args);做更严格的参数匹配。这种类型的MethodMathcer称为动态方法匹配。显然,这种类型虽然严格但性能较差。
通过以上3个接口,我们就能灵活的自定义我们需要的Pointcut类型。但强大的Spring已经预定义好了足够的pointcut。大多数情况我们只需直接调用那些预留的pointcut即可满足需求了。比如 JdkRegexpMethodPointcut ControlFlowPointcut等等。
最后一点需要注意的是,就像例子中展示的那样,pointcut一般不在配置文件中显示的注入(当然你可以这样配置,这并不违反spring的原则),而是一个隐藏在幕后的英雄。

四)AOP的Aspect
AOP API中的Aspect叫做Advisor.而与一般的一个Aspect可以对应多个pointcut和advice不同。一个Advisor只能对应一个advice和一个pointcut。
同样的,spring也已经提供了许多的预定义的Advisor.一般情况下,已经不需要我们去自定义了。而这些预定义好的Advisor大致可以分成两类:PointcutAdvisor 和 IntroductionAdvisor。
DefaultPointcutAdvisor是最通用的Advisor实现。除了不能为其指定Introduction类型的Advice之外。其它所有的Advice和Pointcut都可以通过DefaultPointcutAdvisor来使用。

五)AOP的织入
就如上面的例子所示,由ProxyFactory类负责织入。由代码织入的例子如下:
ProxyFactory weaver = new ProxyFactory(yourTargetObject);
Advisor advisor = ...;
weaver.addAdvisor(advisor );
Object proxyObject = weaver.getProxy();
//现在你可以使用proxyObject了

当然,你还可以调用weaver.addAdvice(...);直接指定各种类型的Advice。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值