浅谈spring——切面(七)

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

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

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.xsd
	http://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.greetTo
How are you!Tom!
-----------end---------------
waiter greet to Tom!
waiter serving Tom!
seller greet to Tom!


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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值