实例分析,AOP的静态代理和动态代理

源码获取github

1.什么是AOP?

Aspect Oriented Programming with Spring 面向切面(方面)编程

  • 面向切面编程是面向对象编程的一个补充而已
  • 白话:我的理解—->在不改变原来的代码的基础上增强(增加)新的功能

2.代码结构

3.情景描述引发静态代理

如果现在让你完成一个2个数的四则运算

  • 核心业务完成

    package com.hs.service;
    
    /** * 对外提供的核心业务,完成了加法/减法/乘法/除法运算 */
    public interface ArithmeticService {
     int add(int x, int y);
    
     int sub(int x, int y);
    
     int mul(int x, int y);
    
     int div(int x, int y);
    }
    package com.hs.service;
    
    /** * 核心代码 */
    public class ArithmeticServiceImpl implements ArithmeticService {
     @Override
     public int add(int x, int y) {
        //核心代码
        int result = x + y;
        return result;
     }
    
     @Override
     public int sub(int x, int y) {
        int result = x - y;
        return result;
     }
    
     @Override
     public int mul(int x, int y) {
        int result = x * y;
        return result;
     }
    
     @Override
     public int div(int x, int y) {
        int result = x / y;
        return result;
     }
    }
  • 完成了,和尚—>技术经理—>定义接口,悟空程序员—>接口实现类

  • 交工客户龙王,龙王需要显示传递数据的信息功能—>和尚—>悟空完成客户需求,但是万一如果又不要这个功能呢,现在引出静态代理,在核心代码的基础上增加新的功能

    package com.hs.service;
    
    /** * 新增加的功能,采用静态代理 */
    public class ArithmeticServiceLogImpl implements ArithmeticService {
    
     //声明一个核心代码类的变量,为了后面方便调用核心代码的功能
     private ArithmeticServiceImpl asc = new ArithmeticServiceImpl();
    
     @Override
     public int add(int x, int y) {
        //后增加的某个功能
        System.out.println("加法传递的参数===>x="+x+",y="+y);
    // 然后调用核心代码的功能
        return asc.add(2, 3);
     }
    
     @Override
     public int sub(int x, int y) {
        System.out.println("减法传递的参数===>x="+x+",y="+y);
        return asc.sub(2, 3);
     }
    
     @Override
     public int mul(int x, int y) {
        System.out.println("乘法传递的参数===>x="+x+",y="+y);
        return asc.mul(2, 3);
     }
    
     @Override
     public int div(int x, int y) {
        System.out.println("除法传递的参数===>x="+x+",y="+y);
        return asc.mul(2, 3);
     }
    }

测试:

package com.hs.test;

import com.hs.proxy.ArithmeticServiceProxy;
import com.hs.service.ArithmeticService;
import com.hs.service.ArithmeticServiceImpl;
import org.junit.Before;
import org.junit.Test;

import java.lang.reflect.Proxy;

public class ArithmeticServiceTest {

   private ArithmeticService arithmeticService;

   @Before //在每个单元测试运行之前都要进行这个方法
   public void init() {
      this.arithmeticService = new ArithmeticServiceLogImpl();//new ArithmeticServiceImpl(); //想用哪个功能就实例化哪个类
   }

   @Test
   public void testAddMethod() {
      int result = this.arithmeticService.add(2, 3);
      System.out.println(result);
   }
}

4.动态代理

接口和核心代码不变,

代理类:

package com.hs.proxy;

import com.hs.service.ArithmeticService;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Arrays;

/** * 代理类 */
public class ArithmeticServiceProxy implements InvocationHandler {

   //定义一个接口变量
   private ArithmeticService arithmeticService;

   public ArithmeticServiceProxy(ArithmeticService arithmeticService) {
      this.arithmeticService = arithmeticService;
   }

   @Override
   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      //写了某个功能,不管程序有没有错误都执行
      System.out.println("在运行方法[" + method.getName() + "]之前执行,传递的参数为" + Arrays.asList(args));
      Object result = null;
      try {
         result = method.invoke(this.arithmeticService, args);
         //写了某个功能,只有程序没有错误才执行
         System.out.println("运行方法成功,结果为:"+result);
      } catch (Exception e) {
         e.printStackTrace();
         //写了某个功能,程序有错误的时候才执行
         System.out.println("执行的方法错误");
      }
      //写了某个功能,不管程序有没有错误都执行
      System.out.println("在运行方法之后执行");
      return result;
   }
}

测试

package com.hs.test;

import com.hs.proxy.ArithmeticServiceProxy;
import com.hs.service.ArithmeticService;
import com.hs.service.ArithmeticServiceImpl;
import org.junit.Before;
import org.junit.Test;

import java.lang.reflect.Proxy;

public class ArithmeticServiceTest {

   private ArithmeticService arithmeticService;

   @Before //再每个单元测试运行之前都要进行这个方法
   public void init() {
      this.arithmeticService = new ArithmeticServiceImpl();    //想用哪个功能就实例化哪个
   }
   /** * 动态代理 */
   @Test
   public void test01() {
      //实例化代理类
      ArithmeticServiceProxy asp = new ArithmeticServiceProxy(this.arithmeticService);
// 固定写法
      ArithmeticService as = (ArithmeticService) Proxy.newProxyInstance(ArithmeticServiceImpl.class.getClassLoader(), ArithmeticServiceImpl.class.getInterfaces(), asp);

      int result = as.div(10, 1);
      System.out.println(result);
   }
}