zoukankan      html  css  js  c++  java
  • 循序渐进之Spring AOP(2)

    学习AOP前要先了解几个重要术语:Joinpoint、Pointcut、Advice

    仍然以改装车比喻,拿到心爱的汽车后想做改装,第一件事是什么?找到要改装的地方。车上可改装的地方很多,但每个人感兴趣的点并不一样,有人改装车灯,有人改装轮毂,也有人同时都改,确定位置后装上零件、装饰,就完成了一次"AOP"。

    在上面的比喻中,可改装的地方可以看做是连接点(Joinpoint),如类的某个方法调用前、调用后、抛出异常等,spring仅支持方法的连接点。

    改装车要告诉改装师傅感兴趣的改装点,同样,在众多的类和方法中,我们需要告诉Spring哪些是我们感兴趣的连接点。AOP通过切点(Pointcut)来描述,例如前一篇中的 "execution(* login(..))" 是告诉Spring我们要找一个名称为login的方法,返回值和参数格式不限。

    最后,标记好Pointcut后,我们就要在目标连接点织入(Weaving)写好的代码,代码写在哪儿?写在增强(Advice,另一种直白的翻译是通知,但是增强更好理解一些,本身作用就是植入目标类添加额外的功能)里。当然,增强并不能是随便一段代码,还必须配合连接点的方位,例如MethodBeforeAdvice就只能织入方法调用前的位置,AfterReturningAdvice只能织入方法返回后的位置。

    看了这么多后,先实战一下。现有一个汽车类,带有一个lock()方法,表示锁车。现在我们希望在锁车后能"哔哔"两声提示车已经锁好。来看过程代码

    [java] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    1. public interface Car {  
    2.     void lock();  
    3. }  
    [java] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    1. public class MyCar implements Car {  
    2.     @Override  
    3.     public void lock() {  
    4.         System.out.println("锁车");  
    5.     }  
    6. }  

    后置增强,在方法正常完成后执行,这里要执行的是输出"哔哔"

    [java] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    1. import java.lang.reflect.Method;  
    2.   
    3. import org.springframework.aop.AfterReturningAdvice;  
    4.   
    5. public class BibiAdvice implements AfterReturningAdvice {  
    6.   
    7.     @Override  
    8.     public void afterReturning(Object returnObj, Method method, Object[] args,  
    9.             Object obj) throws Throwable {  
    10.         System.out.println("哔哔");  
    11.     }  
    12.   
    13. }  

    用代码方式创建代理

    [java] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    1. import org.springframework.aop.AfterReturningAdvice;  
    2. import org.springframework.aop.framework.ProxyFactory;  
    3.   
    4. public class Client {  
    5.     public static void main(String[] args) {  
    6.         Car car = new MyCar();  
    7.         AfterReturningAdvice advice = new BibiAdvice();  
    8.         ProxyFactory pf = new ProxyFactory();  
    9.         pf.setTarget(car);  
    10.         pf.setInterfaces(car.getClass().getInterfaces());  
    11.         pf.addAdvice(advice);  
    12.         Car proxy = (Car)pf.getProxy();  
    13.         proxy.lock();  
    14.     }  
    15. }  

    执行结果

    [java] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    1. 锁车  
    2. 哔哔  

    当然,实际开发中不会使用这种代码的方式,Spring会帮我们完成自动创建代理工作,但从基础做起有助于了解底层实现的技术。

    下面来看其他几种Spring可用的增强:

    前置增强

    [java] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    1. public class BeforeAdviceDemo implements MethodBeforeAdvice {  
    2.     @Override  
    3.     public void before(Method method, Object[] args, Object obj)  
    4.             throws Throwable {  
    5.         System.out.println("锁车前关好窗户");  
    6.     }  
    7. }  

    环绕增强

    [java] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    1. public class AroundAdviceDemo implements MethodInterceptor {  
    2.     @Override  
    3.     public Object invoke(MethodInvocation invocation) throws Throwable {  
    4.         Object[] args = invocation.getArguments();  
    5.         String name = (String)args[0];  
    6.         System.out.println("Hi, " + name);  
    7.         Object obj = invocation.proceed(); //调用目标方法  
    8.         System.out.println("Goodbye! " + name);  
    9.         return obj;  
    10.     }  
    11. }  

    异常抛出

    [java] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    1. public class ThrowsAdviceDemo implements ThrowsAdvice {  
    2.   
    3.     public void afterThrowing(Method method, Object[] args, Object target, Exception ex) throws Throwable {  
    4.         System.out.println("抛出异常:" + ex.getMessage());  
    5.         System.out.println("异常处理...");  
    6.     }  
    7. }  

    另外还有一种特殊的类型Introduction,实现较为复杂暂不演示。

    下一节来演示通过配置文件把这些增强织入的目标类中。

  • 相关阅读:
    [JLOI2010] 冠军调查
    [ZJOI2009] 狼和羊的故事
    [CF1451D] Circle Game
    [CF1451E1] Bitwise Queries (Easy Version)
    [CF343D] Water Tree
    [CF1344B] Monopole Magnets
    [CF191C] Fools and Roads
    [CF1370D] Odd-Even Subsequence
    [CF1366D] Two Divisors
    [CF1359D] Yet Another Yet Another Task
  • 原文地址:https://www.cnblogs.com/sa-dan/p/6837177.html
Copyright © 2011-2022 走看看