• AOP面向切面编程


    一、静态代理

    1.接口

    1 package com.zhidi.service;
    2 
    3 public interface PayService {
    4     /*
    5      * 支付方法
    6      */
    7     public boolean pay(String userName,double money);
    8  
    9 }
    View Code

    2.目标对象(实现接口)

     1 package com.zhidi.service.imp;
     2 
     3 import com.zhidi.service.PayService;
     4 /*
     5  * 目标对象
     6  */
     7 public class QQPayService implements PayService {
     8 
     9     @Override
    10     public boolean pay(String userName, double money) {
    11         
    12         System.out.println(userName+"用QQ支付了"+money+"块钱");
    13         return true;
    14     }
    15 
    16 }
    View Code
     1 package com.zhidi.service.imp;
     2 
     3 import com.zhidi.service.PayService;
     4 /*
     5  * 目标对象
     6  */
     7 public class WxPayService implements PayService {
     8 
     9     @Override
    10     public boolean pay(String userName, double money) {
    11         System.out.println(userName+"用微信支付了"+money+"块钱");
    12         return true;
    13     }
    14 
    15 }
    View Code

    3.代理类(实现接口)

     1 package com.zhidi.service.proxy;
     2 
     3 import com.zhidi.service.PayService;
     4 /*
     5  * 静态代理类
     6  */
     7 public class PayServiceProxy implements PayService {
     8     //引用目标对象
     9     private PayService target;
    10     
    11     public PayServiceProxy(PayService target) {
    12         this.target = target;
    13     }
    14 
    15     @Override
    16     public boolean pay(String userName, double money) {
    17         before(userName, money);
    18         //调用目标对象的pay方法完成支付
    19         boolean result=target.pay(userName, money);
    20         after(userName, money, result);
    21         return result;
    22     }
    23 
    24     //增加额外的功能
    25     public void before(String userName, double money)
    26     {
    27         System.out.println(userName+"准备用"+money+"钱");
    28     }
    29     
    30     public void after(String userName, double money,boolean result)
    31     {
    32         if(result)
    33         {
    34             System.out.println("用钱成功");
    35         }else
    36         {
    37             System.out.println("用钱失败");
    38         }
    39     }
    40 }
    View Code

    4.测试

     1 package com.zhidi.service.test;
     2 
     3 
     4 import com.zhidi.service.imp.QQPayService;
     5 import com.zhidi.service.proxy.PayServiceProxy;
     6 
     7 public class TestStaticProxy {
     8     public static void main(String[] args) {
     9         //创建代理对象并为其指定代理的目标对象
    10         PayServiceProxy proxy=new PayServiceProxy(new QQPayService());
    11         proxy.pay("尼古拉斯·赵四", 20000);
    12     }
    13 
    14 }
    View Code

    二、动态代理

    1.接口

    1 package com.zhidi.service;
    2 
    3 public interface PayService {
    4     /*
    5      * 支付方法
    6      */
    7     public boolean pay(String userName,double money);
    8  
    9 }
    View Code

    2.目标对象

     1 package com.zhidi.service.imp;
     2 
     3 import com.zhidi.service.PayService;
     4 /*
     5  * 目标对象
     6  */
     7 public class QQPayService implements PayService {
     8 
     9     @Override
    10     public boolean pay(String userName, double money) {
    11         
    12         System.out.println(userName+"用QQ支付了"+money+"块钱");
    13         return true;
    14     }
    15 
    16 }
    View Code
     1 package com.zhidi.service.imp;
     2 
     3 import com.zhidi.service.PayService;
     4 /*
     5  * 目标对象
     6  */
     7 public class WxPayService implements PayService {
     8 
     9     @Override
    10     public boolean pay(String userName, double money) {
    11         System.out.println(userName+"用微信支付了"+money+"块钱");
    12         return true;
    13     }
    14 
    15 }
    View Code

    3.代理类

     1 package com.zhidi.service.proxy;
     2 
     3 import java.lang.reflect.InvocationHandler;
     4 import java.lang.reflect.Method;
     5 
     6 import com.zhidi.service.PayService;
     7 
     8 /*
     9  * 动态代理
    10  */
    11 public class DynamicServiceProxy implements InvocationHandler {
    12     //目标对象
    13     private PayService payService;
    14 
    15     public DynamicServiceProxy(PayService payService) {
    16         this.payService = payService;
    17     }
    18 
    19     @Override
    20     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    21         //参数在args数组中
    22         before((String) args[0], (double) args[1]);
    23         //调用目标对象的目标方法
    24         Object result = method.invoke(payService, args);
    25         after((String) args[0], (double) args[1], (boolean) result);
    26         return result;
    27     }
    28 
    29     // 增加额外的功能
    30     public void before(String userName, double money) {
    31         System.out.println(userName + "准备用" + money + "钱");
    32     }
    33 
    34     public void after(String userName, double money, boolean result) {
    35         if (result) {
    36             System.out.println("用钱成功");
    37         } else {
    38             System.out.println("用钱失败");
    39         }
    40     }
    41 
    42 }
    View Code

    4.测试

     1 package com.zhidi.service.test;
     2 
     3 import java.lang.reflect.Proxy;
     4 
     5 import com.zhidi.service.PayService;
     6 import com.zhidi.service.imp.QQPayService;
     7 import com.zhidi.service.proxy.DynamicServiceProxy;
     8 
     9 public class TestDynamicProxy {
    10     public static void main(String[] args) {
    11         // proxy的newProxyInstance()方法用于为目标对象创建代理对象,目标对象和代理对象实现相同的接口
    12         // ClassLoader loader:类加载器
    13         // interfacers:目标对象实现的接口
    14         // h:代理对象通过该对象实现对目标的增强
    15         PayService proxy = (PayService) Proxy.newProxyInstance(TestDynamicProxy.class.getClassLoader(),
    16                 new Class[] { PayService.class }, new DynamicServiceProxy(new QQPayService()));
    17 
    18         proxy.pay("刘能", 20000);
    19     }
    20 
    21 }
    View Code

    三、基于xml的Spring AOP

    1.接口

    1 package com.zhidi.service;
    2 
    3 public interface PayService {
    4     /*
    5      * 支付方法
    6      */
    7     public boolean pay(String userName,double money);
    8  
    9 }
    View Code

    2.目标对象

     1 package com.zhidi.service.imp;
     2 
     3 import com.zhidi.service.PayService;
     4 /*
     5  * 目标对象
     6  */
     7 public class QQPayService implements PayService {
     8 
     9     @Override
    10     public boolean pay(String userName, double money) {
    11         
    12         System.out.println(userName+"用QQ支付了"+money+"块钱");
    13         return true;
    14     }
    15 
    16 }
    View Code
     1 package com.zhidi.service.imp;
     2 
     3 import com.zhidi.service.PayService;
     4 /*
     5  * 目标对象
     6  */
     7 public class WxPayService implements PayService {
     8 
     9     @Override
    10     public boolean pay(String userName, double money) {
    11         System.out.println(userName+"用微信支付了"+money+"块钱");
    12         return true;
    13     }
    14 
    15 }
    View Code

    3.通知类

     1 package com.zhidi.advice;
     2 
     3 import org.aspectj.lang.ProceedingJoinPoint;
     4 
     5 /*
     6  * 通知类
     7  */
     8 public class LogAdvice {
     9     
    10     //前置通知
    11     public void before()
    12     {
    13         System.out.println("前置通知");
    14     }
    15     //后置通知
    16     public void after()
    17     {
    18         System.out.println("后置通知");
    19     }
    20     //带参数的前置通知
    21     public void beforeLog(String userName, double money)
    22     {
    23         System.out.println(userName+"准备用"+money+"钱");
    24     }
    25     //带参数的后置返回通知
    26     public void afterLog(String userName, double money,boolean result)
    27     {
    28         if(result)
    29         {
    30             System.out.println("用钱成功");
    31         }else
    32         {
    33             System.out.println("用钱失败");
    34         }
    35     }
    36     //异常返回通知,是有参的,
    37     public void afterThrowing(Exception e)
    38     {
    39         System.out.println(e.getMessage());
    40     }
    41     //后通知,无论什么情况都会执行的,
    42     public void afterFinally()
    43     {
    44         System.out.println("最终返回通知,无论怎样都会执行");
    45     }
    46     //环绕通知,是有返回值的,不需要设置
    47     public Object around(ProceedingJoinPoint joinPoint) throws Throwable
    48     {
    49         //环绕前通知
    50         System.out.println("环绕前通知");
    51         Object result=    joinPoint.proceed();
    52         //环绕后通知
    53         System.out.println("环绕后通知");
    54         return result;
    55     }
    56     
    57 }
    View Code

    4.测试

     1 package com.zhidi.service.test;
     2 
     3 import org.springframework.context.ApplicationContext;
     4 import org.springframework.context.support.ClassPathXmlApplicationContext;
     5 
     6 import com.zhidi.service.PayService;
     7 
     8 public class TestAop {
     9 
    10     public static void main(String[] args) {
    11        ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml"); 
    12        //通过id获得指定的目标对象
    13        PayService payService= context.getBean("wxPayService",PayService.class);
    14        payService.pay("黄老邪", 30000);
    15     }
    16 }
    View Code

    5.applicationContext.xml配置

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
     4     xmlns:context="http://www.springframework.org/schema/context"
     5     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
     6         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
     7         http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
     8     <!-- 将目标对象交给Spring的IOC容器管理 -->
     9     <bean id="QQPayService" class="com.zhidi.service.imp.QQPayService" />
    10     <bean id="wxPayService" class="com.zhidi.service.imp.WxPayService" />
    11     <!-- 将切面支持类纳入Spring的IoC容器管理 ,该类中定义通知实现方法 -->
    12     <bean id="logAdvice" class="com.zhidi.advice.LogAdvice" />
    13     <!-- aop定义开始 -->
    14     <aop:config>
    15         <!-- 定义全局切入点,该切入点可以应用于多个切面定义中 expression="execution(public boolean com.zhidi.service.imp.QQPayService.pay(java.lang.String,java.lang.Double)) -->
    16         <aop:pointcut expression="execution(* com.zhidi.service..*.pay(..))"
    17             id="pointcut" />
    18         <!-- 定义切面,同时指定该切面所需的切面支持类(通知所在类) -->
    19         <aop:aspect ref="logAdvice">
    20             <!-- 定义前置通知, -->
    21             <aop:before method="before" pointcut-ref="pointcut" />
    22             <!-- 后置返回通知 -->
    23             <aop:after-returning method="after" pointcut-ref="pointcut" />
    24             <!-- 前置通知,带有参数 -->
    25             <aop:before method="beforeLog"
    26                 pointcut="execution(* com.zhidi.service..*.pay(..)) and args(userName,money)"
    27                 arg-names="userName,money" />
    28             <!-- 带参数的后置返回通知 -->
    29             <aop:after-returning method="afterLog"
    30                 pointcut="execution(* com.zhidi.service..*.pay(..)) and args(userName,money)"
    31                 returning="result" arg-names="userName,money,result" />
    32             <!-- 异常返回通知 -->
    33             <aop:after-throwing method="afterThrowing"
    34                 pointcut-ref="pointcut" throwing="e" />
    35             <!-- 后通知 -->
    36             <aop:after method="afterFinally" pointcut-ref="pointcut" />
    37             <!-- 环绕通知 -->
    38             <aop:around method="around" pointcut-ref="pointcut" />
    39         </aop:aspect>
    40     </aop:config>
    41 
    42 </beans>
    View Code

    四、基于@AspectJ风格的AOP(接口、目标对象和测试以上一样)

    1.通知类

     1 package com.zhidi.advice;
     2 
     3 import org.aspectj.lang.ProceedingJoinPoint;
     4 import org.aspectj.lang.annotation.After;
     5 import org.aspectj.lang.annotation.AfterReturning;
     6 import org.aspectj.lang.annotation.AfterThrowing;
     7 import org.aspectj.lang.annotation.Around;
     8 import org.aspectj.lang.annotation.Aspect;
     9 import org.aspectj.lang.annotation.Before;
    10 import org.springframework.stereotype.Component;
    11 
    12 /*
    13  * 通知类
    14  */
    15 //基于@Aspect的AOP
    16 @Component // 将当前的Bean交给Spring的IOC容器管理
    17 @Aspect // 将该Bean定义为切面
    18 public class LogAonnection {
    19 
    20     // 前置通知
    21     @Before("execution(* com.zhidi.service..*.*(..))")
    22     public void before() {
    23         System.out.println("前置通知");
    24     }
    25 
    26     // 后置通知
    27     @AfterReturning("execution(* com.zhidi.service..*.*(..))")
    28     public void after() {
    29         System.out.println("后置通知");
    30     }
    31 
    32     // 带参数的前置通知
    33     @Before(value = "execution(* com.zhidi.service..*.*(..)) and args(userName,money)", argNames = "userName,money")
    34     public void beforeLog(String userName, double money) {
    35         System.out.println(userName + "准备用" + money + "钱");
    36     }
    37 
    38     // 带参数的后置返回通知
    39     @AfterReturning(value = "execution(* com.zhidi.service..*.*(..)) and args(userName,money)", returning = "result", argNames = "userName,money,result")
    40     public void afterLog(String userName, double money, boolean result) {
    41         if (result) {
    42             System.out.println("用钱成功");
    43         } else {
    44             System.out.println("用钱失败");
    45         }
    46     }
    47 
    48     // 异常返回通知,是有参的,
    49     @AfterThrowing(value = "execution(* com.zhidi.service..*.*(..))", throwing = "e")
    50     public void afterThrowing(Exception e) {
    51         System.out.println(e.getMessage());
    52     }
    53 
    54     // 后通知,无论什么情况都会执行的,
    55     @After(value = "execution(* com.zhidi.service..*.*(..))")
    56     public void afterFinally() {
    57         System.out.println("最终返回通知,无论怎样都会执行");
    58     }
    59 
    60     // 环绕通知,是有返回值的,不需要设置
    61     @Around(value = "execution(* com.zhidi.service..*.*(..))")
    62     public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
    63         // 环绕前通知
    64         System.out.println("环绕前通知");
    65         Object result = joinPoint.proceed();
    66         // 环绕后通知
    67         System.out.println("环绕后通知");
    68         return result;
    69     }
    70 
    71 }
    View Code

    2.applicationContext.xml配置

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
     4     xmlns:context="http://www.springframework.org/schema/context"
     5     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
     6         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
     7         http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
     8     <!-- 开启注解配置 -->
     9     <context:component-scan base-package="com.zhidi"/>
    10     <!-- aspectj注解配置  -->
    11     <aop:aspectj-autoproxy/> 
    12     <!-- 将目标对象交给Spring的IOC容器管理 -->
    13     <bean id="QQPayService" class="com.zhidi.service.imp.QQPayService" />
    14     <bean id="wxPayService" class="com.zhidi.service.imp.WxPayService" />
    15 
    16 
    17 </beans>
    View Code

     

  • 相关阅读:
    第3章 Python的数据结构、函数和文件
    字符与编码
    第2章 IPython和Jupyter
    第1章 准备工作
    (转)详解Python的装饰器
    (转)Python中的split()函数
    5.5 用户定义的可调用类型
    2.6 序列的增量赋值
    Zookeeper简析
    Dubbo-服务引入源码分析
  • 原文地址:https://www.cnblogs.com/zclqian/p/7454977.html
Copyright © 2020-2023  润新知