基于SpringBoot实现AOP之JDK/CGlib动态代理详解

动态代理是一种设计模式。

在Spring中,有两种方式可以实现动态代理--JDK动态代理和CGLIB动态代理。

Spring 中 Aop 的实现

如果代理对象有接口,就用 JDK 动态代理。

JDK 动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法时,会先调用实现了 InvokeHandler 接口的 invoke() 方法,来实现业务增强

如果代理对象没有接口,那么就直接使用 Cglib 动态代理。

Cglib 动态代理是利用 asm 开源包,对代理对象类的 class 文件加载进来,通过修改其字节码生成子类来处理

JDK动态代理实现:

首先定一个父类接口

public interface Person {
    void study();
}

实现该父类接口-学生要学习

public class Student implements Person{
    @Override
    public void study() {
        System.out.println("学生要学习");
    }
}

然后我们创建一个动态代理类,需要实现InvocationHandler接口

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @Describe TODO:
 * @Author dora 1.0.1
 **/
public class AnimalInvocationHandler implements InvocationHandler {
    private Object target;

    public Object bind(Object target) {
        this.target = target;
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = null;
        System.out.println("----调用前处理");
        result = method.invoke(target, args);
        System.out.println("----调用后处理");
        return result;
    }

    public static void main(String[] args) {
        Student dog = new Student();
        AnimalInvocationHandler ani = new AnimalInvocationHandler();
        Person proxy = (Person)ani.bind(dog);
        proxy.study();
    }
}

运行结果如下:

 

分析总结

想要在student对象前后加上额外的逻辑,可以不直接修改study方法。

这就是AOP实现的基本原理,只是Spring不需要开发人员自己维护。

但是这么实现有个缺点,那就是必须实现接口。很烦人。所以我们要用CGLIB了

CGLIB动态代理:

首先。这玩意正常来说应该是Spring框架自带有的。在spring-core依赖包中
给个下载Maven地址吧:https://mvnrepository.com/artifact/org.springframework/spring-core/5.3.22

<!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>5.3.22</version>
</dependency>

确定已经存在该依赖后,那就到我们编写代码Dome拉

首先我们一样先上个父类-Teacher类(这时候已经不需要有接口了直接是实现方法)

public class Teacher {
    public void play(){
        System.out.println("老师改作业");
    }
}

然后就是开始重写MethodInterceptor

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * @Describe TODO:
 * @Author dora 1.0.1
 **/
public class TeacherMethodIntercepto implements MethodInterceptor {
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("调用前。。。");
        Object obj = methodProxy.invokeSuper(o,objects);
        System.out.println("调用后。。。");
        return obj;
    }

    public static void main(String[] args) {
        Enhancer en = new Enhancer();
        en.setSuperclass(Teacher.class);
        en.setCallback(new TeacherMethodIntercepto());
        Teacher t = (Teacher)en.create();
        t.play();
    }
}

运行结果如下:

 

AOP#

面向切面编程是面向对象编程的一种补充。

以Java为例,提供了封装,继承,多态等概念,实现了面向对象编程。但是假如我们要实现以下场景:给每个类设置权限拦截器。

如果不用AOP思想,我们可能要疯掉。因为会有大量代码重用重写。但是AOP的出现提供“横向”的逻辑,将与多个对象有关的公共模块分装成一个可重用模块,并且将这个模块整合成Aspect,即切面。

AOP的一些概念,整理成表如下:

名称概念
横切关注点一个横切需求(例如日志)
切面一个横切关注点可能有多个对象
连接点一个方法的执行
切入点AspectJ的切入点语法
通知拦截后的动作
目标对象业务中需要增强的对象
织入将切面作用到对象
引入不用定义接口就能使用其中的方法

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值