浅谈spring——切面(七)

来源:互联网 发布:windows编程四大宝书 编辑:程序博客网 时间:2024/05/24 01:28

之前提到的五大增强是被织入目标类的所有方法中。

但如果想选择性增强(织入某些类的某些方法上),则要借助于切点。

spring 主要通过org.springframework.aop.Pointcut 来描述切点


Pointcut接口定义

public interface Pointcut {/** * Return the ClassFilter for this pointcut. * @return the ClassFilter (never <code>null</code>) */ClassFilter getClassFilter();/** * Return the MethodMatcher for this pointcut. * @return the MethodMatcher (never <code>null</code>) */MethodMatcher getMethodMatcher();/** * Canonical Pointcut instance that always matches. */Pointcut TRUE = TruePointcut.INSTANCE;}
PointCut主要依赖于ClassFilter和MethodMatcher,通过ClassFilter可以定位到某些特定类中,通过MethodMatcher可以定位到某些具体方法。


切面:由切点和增强代码两部分组成。

spring用org.springframework.aop.Advisor表示切面。切面分三类:一般切面、切点切面、引介切面。


1. Advisor:表示一般的切面,仅依赖一个增强接口Advice,作用于目标类的所有方法,使用较少

2. PointcutAdvisor:表示具有切点的切面。包含了增强部分(Advice)和切点(Pointcut),可以灵活的针对某些特定的类、方法增强。

3. IntroductionAdvisor:对应引介增强的特殊的切面。

其中第2点的PointcutAdvisor使用场景最多,我们看下它的子类结构


a)DefaultPointcutAdvisor,通过任意Pointcut和Advice定义一个切面,不支持引介的切面类型,可以通过扩展子类实现自定义的切面

b)NameMatchMethodPointcutAdvisor,按方法名定义切点的切面

c)RegexpMethodPointcutAdvisor,按正则表达式匹配方法名进行切点定义的切面

d)AspectJExpressionPointcutAdvisor,用AspectJ切点表达式定义切点的切面

e)AspectJPointcutAdvisor,用AspectJ语法定义切点的切面

f)StaticMethodMatcherPointcutAdvisor,静态方法匹配器切点定义的切面,默认匹配所有的目标类


例子:

Seller.java

package tome.sample.Advisor;/** * 类Seller.java的实现描述:TODO 类实现描述 *  * @author onlyone 2013-4-13 下午08:41:36 */public class Seller {    public void greetTo(String name) {        System.out.println("seller greet to " + name + "!");    }}

Waiter.java

package tome.sample.Advisor;/** * 类Waiter.java的实现描述:TODO 类实现描述 *  * @author onlyone 2013-4-13 下午08:41:44 */public class Waiter {    public void greetTo(String name) {        System.out.println("waiter greet to " + name + "!");    }    public void serveTo(String name) {        System.out.println("waiter serving " + name + "!");    }}


自定义切面GreetingAdvisor.java

package tome.sample.Advisor;import java.lang.reflect.Method;import org.springframework.aop.ClassFilter;import org.springframework.aop.support.StaticMethodMatcherPointcutAdvisor;/** * 自定义切面 *  * @author onlyone 2013-4-13 下午08:42:10 */public class GreetingAdvisor extends StaticMethodMatcherPointcutAdvisor {    /**     * 匹配greetTo方法     */    public boolean matches(Method method, Class clazz) {        return "greetTo".equals(method.getName());    }    /**     * 匹配Waiter及其子类     */    public ClassFilter getClassFilter() {        return new ClassFilter() {            public boolean matches(Class clazz) {                return Waiter.class.isAssignableFrom(clazz);            }        };    }}

前置增强GreetingBeforeAdvice.java

package tome.sample.Advisor;import java.lang.reflect.Method;import org.springframework.aop.MethodBeforeAdvice;/** * 前置增强 *  * @author onlyone 2013-4-13 下午08:49:02 */public class GreetingBeforeAdvice implements MethodBeforeAdvice {    public void before(Method method, Object[] args, Object obj) throws Throwable {        String clientName = (String) args[0];        System.out.println("-----------begin---------------");        System.out.println("GreetingBeforeAdvice is successfully called! "+obj.getClass().getName() + "." + method.getName());        System.out.println("How are you!" + clientName + "!");        System.out.println("-----------end---------------");    }}

xml配置文件

<?xml version="1.0" encoding="UTF-8" ?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"xmlns:util="http://www.springframework.org/schema/util"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd"><!-- 普通方法名匹配切面 --><bean id="waiterTarget" class="tome.sample.Advisor.Waiter" /><bean id="sellerTarget" class="tome.sample.Advisor.Seller" /><bean id="greetingAdvice" class="tome.sample.Advisor.GreetingBeforeAdvice" /><bean id="greetingAdvisor" class="tome.sample.Advisor.GreetingAdvisor"><property name="advice" ref="greetingAdvice" /></bean><bean id="parent" abstract="true"class="org.springframework.aop.framework.ProxyFactoryBean"p:interceptorNames="greetingAdvisor" p:proxyTargetClass="true" /><bean id="waiter" parent="parent"><property name="target" ref="waiterTarget" /></bean><bean id="seller" parent="parent"><property name="target" ref="sellerTarget" /></bean></beans>

测试类

package tome.sample.Advisor;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;/** * 测试类 *  * @author onlyone 2013-4-13 下午08:59:36 */public class TestAdvisor {    public static void main(String[] args) {        String configPath = "beans.xml";        ApplicationContext ctx = new ClassPathXmlApplicationContext(configPath);        Waiter waiter = (Waiter) ctx.getBean("waiter");        Seller seller = (Seller) ctx.getBean("seller");        waiter.greetTo("Tom");        waiter.serveTo("Tom");        seller.greetTo("Tom");    }}

运行结果:

-----------begin---------------GreetingBeforeAdvice is successfully called! tome.sample.Advisor.Waiter.greetToHow are you!Tom!-----------end---------------waiter greet to Tom!waiter serving Tom!seller greet to Tom!


代码地址:https://webx-schema.googlecode.com/svn/trunk 

原创粉丝点击