Spring基础:AOP编程(3)

阅读更多
基于切面的AOP编程

通过Advice,可以创建方法前,后,环绕之类的增强,但是这是类级别的增强,如果想要深入到方法级别,就需要配合使用切点Pointcut。Advice和Pointcut组合就形成了一个切面。切面增强就是基于方法层面的。

1.切点(Pointcut)
    用于过滤类,getClassFilter()返回ClassFilter类,在这个类里面有一个方法用于判断该对象是否满足匹配条件,boolean matches(Class clazz)。
    用于过滤方法,getMethodMatcher()返回MethodMatcher,在该类里面有boolean matches(Method method, Class targetClass)用于静态匹配方法,boolean matches(Method method, Class targetClass, Object[] args)用于动态匹配。

2 切点的分类
  • StaticMethodMatcherPointcut 静态方法切点
  • DynamicMethodMatcherPointcut 动态方法切点
  • AnnotationMatchingPointcut 注解切点
  • AspectJExpressionPointcut 支持AspectJ语法的表达式切点
  • ControlFlowPointcut 流程切点
  • ComposablePointcut 复合切点


静态方法切点又分两种
  • NameMatchMethodPointcut 用于方法名匹配
  • JdkRegexpMethodPointcut 用于正则匹配


3 切面
  切面分三种
  • Advisor 一般切面,仅包含一个增强方法,不包含切点信息
  • PointcutAdvisor 包含切点的切面,用起来比较灵活
  • IntroductionAdvisor 引介切面


而PointcutAdvisor又分为以下6种
  • DefaultPointcutAdvisor 最常用的切面,可以通过任意组合切点和增强构建切面
  • NameMatchMethodPointcutAdvisor 通过方法名来定义切面
  • RegexpMethodPointcutAdvisor 通过正则表达式匹配方法名来定义切面
  • StaticMethodMatcherPointcutAdvisor 默认情况下,匹配所有目标类
  • AspectJExpressionPointcutAdvisor 用AspectJ切点表达式来匹配
  • AspectJPointcutAdvisor 用AspectJ语法来匹配


4 例子
准备基础类和一个增强类
public class Waiter {
    public void greetTo(String name) {
        System.out.println("waiter greet to " + name + "...");
    }
    
    public void serveTo(String name) {
        System.out.println("waier serving to " + name + "...");
    }
}
public class Seller {
    public void greetTo(String name) {
        System.out.println("seller greet to " + name + "...");
    }
}个
// 前置增强
public class GreetingBeforeAdvice implements MethodBeforeAdvice {

    public void before(Method method, Object[] args, Object obj)
            throws Throwable {
        System.out.println(obj.getClass().getName() + "." + method.getName());
        String clientName = (String) args[0];
        System.out.println("How are you! Mr." + clientName);
    }
}

4.1 静态方法匹配:
public class GreetingAdvisor extends StaticMethodMatcherPointcutAdvisor {
    public boolean matches(Method method, Class targetClass) {
        return "greetTo".equals(method.getName());
    }
    public ClassFilter getClassFilter() {
        return new ClassFilter() {
            public boolean matches(Class clazz) {
                return Waiter.class.isAssignableFrom(clazz);
            }
        };
    }
}

因为GreetingAdvisor类中已经包含切点信息,所以只要配置增强类即可。









测试:
String configPath = "com/firethewhole/maventest07/advisor/beans.xml";
ApplicationContext ctx = new ClassPathXmlApplicationContext(configPath);
Waiter waiter = (Waiter) ctx.getBean("waiter");
Seller seller = (Seller) ctx.getBean("seller");
waiter.greetTo("John");
waiter.serveTo("John");
seller.greetTo("John");


输出:
只有Waiter类的greetTo方法被织入增强

com.firethewhole.maventest07.advisor.Waiter.greetTo
How are you! Mr.John
waiter greet to John...
waier serving to John...
seller greet to John...


4.2 正则匹配方法名增强

    
        .*greet.*
    



Waiter waiter1 = (Waiter) ctx.getBean("waiter1");
waiter1.greetTo("John");
waiter1.serveTo("John");


输出:
只有greetTo方法被织入增强

com.firethewhole.maventest07.advisor.Waiter.greetTo
How are you! Mr.John
waiter greet to John...
waier serving to John...


4.3 动态方法匹配
动态方法匹配之前都会先进性静态方法匹配,如果失败才会进行
public class GreetingDynamicPointcut extends DynamicMethodMatcherPointcut {
    private static List specialClientList = new ArrayList();
    static {
        specialClientList.add("John");
        specialClientList.add("Tom");
    }
    public ClassFilter getClassFilter() {
        return new ClassFilter() {
            public boolean matches(Class clazz) {
                System.out.println("调用getClassFilter()对" + clazz.getName() + "做静态检查。");
                return Waiter.class.isAssignableFrom(clazz);
            }
        };
    }
    public boolean matches(Method method, Class clazz) {
        System.out.println("调用matches(method,clazz)对" + clazz.getName() + "." + method.getName() + "做静态检查。");
        return "greetTo".equals(method.getName());
    }
    public boolean matches(Method method, Class clazz, Object[] args) {
        System.out.println("调用matches(method,clazz)对" + clazz.getName() + "." + method.getName() + "做动态检查。");
        String clientName = (String) args[0];
        return specialClientList.contains(clientName);
    }
}


 


Waiter waiter2 = (Waiter) ctx.getBean("waiter2");
waiter2.greetTo("Peter");
waiter2.serveTo("Peter");
waiter2.greetTo("John");
waiter2.serveTo("John");

输出:

调用getClassFilter()对com.firethewhole.maventest07.advisor.Waiter做静态检查。
调用matches(method,clazz)对com.firethewhole.maventest07.advisor.Waiter.greetTo做静态检查。
调用getClassFilter()对com.firethewhole.maventest07.advisor.Waiter做静态检查。
调用matches(method,clazz)对com.firethewhole.maventest07.advisor.Waiter.serveTo做静态检查。
调用getClassFilter()对com.firethewhole.maventest07.advisor.Waiter做静态检查。
调用matches(method,clazz)对com.firethewhole.maventest07.advisor.Waiter.toString做静态检查。
调用getClassFilter()对com.firethewhole.maventest07.advisor.Waiter做静态检查。
调用matches(method,clazz)对com.firethewhole.maventest07.advisor.Waiter.clone做静态检查。
调用getClassFilter()对com.firethewhole.maventest07.advisor.Waiter做静态检查。
调用matches(method,clazz)对com.firethewhole.maventest07.advisor.Waiter.greetTo做静态检查。
调用matches(method,clazz)对com.firethewhole.maventest07.advisor.Waiter.greetTo做动态检查。
waiter greet to Peter...
调用getClassFilter()对com.firethewhole.maventest07.advisor.Waiter做静态检查。
调用matches(method,clazz)对com.firethewhole.maventest07.advisor.Waiter.serveTo做静态检查。
waier serving to Peter...
调用matches(method,clazz)对com.firethewhole.maventest07.advisor.Waiter.greetTo做动态检查。
com.firethewhole.maventest07.advisor.Waiter.greetTo
How are you! Mr.John
waiter greet to John...
waier serving to John...


4.4 流程切面
对配置在某一个类中的某一个方法中直接或间接使用的类进行增强
public class WaiterDelegate {
    private Waiter waiter;
    public void setWaiter(Waiter waiter) {
        this.waiter = waiter;
    }
    public void service(String name) {
        waiter.greetTo(name);
        waiter.serveTo(name);
    }
}


    
    




Waiter waiter3 = (Waiter) ctx.getBean("waiter3");
WaiterDelegate wd = new WaiterDelegate();
wd.setWaiter(waiter3);
waiter3.serveTo("Peter");
waiter3.greetTo("Peter");
wd.service("Peter");


输出:
只有流程切点中的才会被织入增强

waier serving to Peter...
waiter greet to Peter...
com.firethewhole.maventest07.advisor.Waiter.greetTo
How are you! Mr.Peter
waiter greet to Peter...
com.firethewhole.maventest07.advisor.Waiter.serveTo
How are you! Mr.Peter
waier serving to Peter...


4.5 复合增强
public class GreetingComposablePointcut {
    public Pointcut getIntersectionPointcut() {
        ComposablePointcut cp = new ComposablePointcut();
        Pointcut pt1 = new ControlFlowPointcut(WaiterDelegate.class, "service");
        Pointcut pt2 = new NameMatchMethodPointcut();
        ((NameMatchMethodPointcut)pt2).addMethodName("greetTo");
        return cp.intersection(pt1).intersection(pt2);
    }
}





Waiter waiter4 = (Waiter) ctx.getBean("waiter4");
WaiterDelegate wd2 = new WaiterDelegate();
wd2.setWaiter(waiter4);
waiter4.serveTo("Peter");
waiter4.greetTo("Peter");
wd2.service("Peter");


输出:
只有流程切点中的方法名为greetTo才会被织入增强

waier serving to Peter...
waiter greet to Peter...
com.firethewhole.maventest07.advisor.Waiter.greetTo
How are you! Mr.Peter
waiter greet to Peter...
waier serving to Peter...


4.6 引介增强
引介增强是类级别的织入,主要的类有DefaultIntroductionAdvisor,配置方法如下:

    
         
  
  • maventest07.zip (56.3 KB)
  • 下载次数: 0

你可能感兴趣的:(spring)