0
点赞
收藏
分享

微信扫一扫

【Spring】AOP的作用和底层原理、AOP相关术语

野见 2022-01-21 阅读 38

文章目录

一、AOP 概述

AOP: 全称是Aspect Oriented Programming,即:面向切面编程。它把程序重复的代码抽取出来,在需要执行的时候,使用动态代理的技术,在不修改源码的基础上,对已有方法进行增强。
在这里插入图片描述

作用: 在程序运行期间,不修改源码对已有方法进行增强
优势: 减少重复代码、提高开发效率、维护方便、
实现方式: 使用动态代理技术

二、动态代理

字节码随用随创建,随用随加载。静态代理是字节码一上来就创建好,并完成加载。装饰者模式就是静态代理的一种体现。

动态代理常用的有两种方式:

  • 基于接口的动态代理
    • 提供者: JDK 官方的Proxy类。
    • 要求: 被代理类最少实现一个接口。
  • 基于子类的动态代理
    • 提供者: 第三方的CGLIB,如果报 asmxxxx 异常,需要导入asm.jar
    • 要求: 被代理类不能用 final 修饰的类(最终类)。

三、使用JDK动态代理

使用java.lang.reflect.Proxy类里面的newProxyInstance()方法创建代理对象

方法介绍:

  • newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h):返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。
    • ClassLoader loader:定义代理类的类加载器
    • Class<?>[] interfaces:代理类要实现的接口列表,支持多个接口
    • InvocationHandler h:实现InvocationHandler接口,创建代理对象,写增强的方法。

第一步: 创建一个接口,待增强的接口

public interface UserDao {
    public int add(int a, int b);
    public String update(String id);
}

第二步: 创建接口实现类,并实现方法

public class UserDaoImpl implements UserDao {
    @Override
    public int add(int a, int b) {
    	System.out.println("add方法执行了...");
        return a + b;
    }

    @Override
    public String update(String id) {
    	System.out.println("update方法执行了...");
        return id;
    }
}

第三步: 创建JDK的接口实现类代理对象

UserDaoProxy类在第四步

public class JDKProxy {
    public static void main(String[] args) {
        // 创建jdk的代理对象
        Class[] interfaces = {UserDao.class};
        UserDaoImpl userDao = new UserDaoImpl();
        UserDao dao = (UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDao));
    }
}

第四步: 创建代理对象

class UserDaoProxy implements InvocationHandler {
    // 增强的逻辑
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        return null;
    }
}

第五步: 将需要增强的对象传递进来

class UserDaoProxy implements InvocationHandler {
    
    // 这是谁的代理对象,就把谁传递进来
    // 可以使用有参构造传递,这里使用Object可以更通用一点,只要是UserDao的实现类都可以传入
    public UserDaoProxy(Object obj) {
        this.obj = obj;
    } 
    
    private Object obj;
    
    // 增强的逻辑
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        return null;
    }
}

第六步: 编写增强代码的逻辑

class UserDaoProxy implements InvocationHandler {

    // 这是谁的代理对象,就把谁传递进来
    // 可以使用有参构造传递,这里使用Object可以更通用一点,只要是UserDao的实现类都可以传入
    public UserDaoProxy(Object obj) {
        this.obj = obj;
    }

    private Object obj;

    // 增强的逻辑
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        // 方法执行之前的操作
        System.out.println("方法执行之前的操作...." + method.getName() + ":传递的参数..." + Arrays.toString(args));

        // 方法执行
        Object res = method.invoke(obj, args);

        // 方法执行之后的操作
        System.out.println("方法执行之后的操作...." + obj + ",方法的返回值:" + res);

        // 将方法的返回值返回
        return res;
    }
}

第七步: 调用增强方法

public class JDKProxy {
    public static void main(String[] args) {
        // 创建jdk的代理对象
        Class[] interfaces = {UserDao.class};
        UserDaoImpl userDao = new UserDaoImpl();
        UserDao dao = (UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDao));
        int res = dao.add(1, 5);
        System.out.println("测试时方法的返回值为:" + res);
    }
}

可以得到结果:
在这里插入图片描述

四、AOP相关术语

Joinpoint(连接点)

Pointcut(切入点)

Advice(通知/增强)

通知的类型:
前置通知:被增强的方法执行之前的通知
后置通知:被增强的方法执行之后的通知
异常通知:被增强的方法出现异常后的通知
最终通知:不管有没有异常都会执行,类似于异常的finally
环绕通知:被增强的方法执行之前之后都做的通知

Aspect(切面)

Introduction(引介)

Target(目标对象)

Weaving(织入)

Proxy(代理)

Spring框架监控切入点方法的执行。一旦监控到切入点方法被运行,使用代理机制,动态创建目标对象的代理对象,根据通知类别,在代理对象的对应位置,将通知对应的功能织入,完成完整的代码逻辑运行。

举报

相关推荐

0 条评论