深入了解SpringAOP中的jdk动态代理与CGlib

 更新时间:2023年12月02日 09:10:18   作者:nuomizhende45  
这篇文章主要介绍了深入了解SpringAOP中的jdk动态代理与CGlib,一般我们编写程序的思想是纵向的,也就是一个方法代码从该方法第一行开始往下一步一步走,直到走完最后一行代码,也就是说很多业务都需要的比如用户鉴权,资源释放等,需要的朋友可以参考下

理解AOP

一般我们编写程序的思想是纵向的,也就是一个方法代码从该方法第一行开始往下一步一步走,直到走完最后一行代码。

也就是说很多业务都需要的比如用户鉴权,资源释放等我们都要在每个方法里面重复再去调用,如下所示:

public void doMethodOne()
{
    System.out.println("doMethodOne由上往下第一步:用户鉴权");
    System.out.println("doMethodOne由上往下第二步:业务逻辑,调用服务1");
    System.out.println("doMethodOne由上往下最后一步:释放资源");
}
public void doMethodTwo()
{
    System.out.println("doMethodTwo由上往下第一步:用户鉴权");
    System.out.println("doMethodTwo由上往下第二步:业务逻辑,调用服务1");
    System.out.println("doMethodTwo由上往下最后一步:释放资源");
}
public static void main(String[] args)
{
    doMethodOne();
    doMethodTwo();
}

AOP(面向切面编程),它可以用来拦截方法前后,来达到增强方法的目的。

所以我理解的AOP的本质是在一系列纵向的控制流程中,把那些相同的子流程提取成一个横向的面,就像下面这张图把相同的逻辑,用户鉴权、资源释放抽取出来,横切到各个需要该场景的方法的开头、中间以及结尾。

SpringAOP中的一些术语

  • 通知(Advice): 何时(Before,After,Around,After还有几个变种) 做什么
  • 连接点(JoinPoint): 应用对象提供可以切入的所有功能(一般是方法,有时也是参数)
  • 切点(PointCut): 通过指定,比如指定名称,正则表达式过滤, 指定某个/些连接点, 切点描绘了 在何地 做
  • 切面(Aspect): 通知 + 切点 何时何地做什么
  • 引入(Introduction):向现有类添加新的属性或方法
  • 织入(Weaving): 就是将切面应用到目标对象的过程

实现方式之JDK的动态代理

JDK动态代理目标是按照接口实现类的形式。

你需要创建一个jdkproxy 类来继承InvocatoinHandler 接口,将你想要增强的代码添加到里面的invoke方法中。

目标类如下

package com.lee.aop.jdkaop;
/**
 * @author lee
 */
public interface UserServiceInf {
     void updateUser();
}
package com.lee.aop.jdkaop;
/**
 * @author lee
 */
public class UserServiceImpl implements UserServiceInf {
    @Override
    public void updateUser()
    {
        System.out.println("修改用户");
    }
}

代理类如下:

package com.lee.aop.jdkaop;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
 * @author lee
 */
public class MyProxy implements InvocationHandler {
    private Object target ;
    public Object getTarget()
    {
        return target;
    }
    public void setTarget(Object target)
    {
        this.target = target;
    }
    public Object createProxy(Object target)
    {
        this.target = target ;
        return Proxy.newProxyInstance(this.target.getClass().
                        getClassLoader(),this.target.getClass().getInterfaces(),this);
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Method methods = this.target.getClass().getMethod("updateUser",null);
        System.out.println("用户鉴权");
        methods.invoke(this.target,null);
        return null;
    }
}

测试类:

package com.lee.aop.jdkaop;
public class Tester {
    public static void main(String[] args) {
        UserServiceImpl userImpl = new UserServiceImpl();
        UserServiceInf service = (UserServiceInf) new MyProxy().createProxy(userImpl);
        service.updateUser();
    }
}

实现方式之CGlib动态代理 

目标类

package com.lee.aop.cglib;
/**
 * @author lee
 */
public class UserService {
    public void updateUser(String uid)
    {
        System.out.println("获取User" + uid);
    }
}

 代理类

package com.lee.aop.cglib;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
 * @author lee
 */
public class UserProxy implements MethodInterceptor {
    //通过Enhacer创建一个代理对象
    Enhancer proxy = new Enhancer();
    public Object getProxy(Class clz)
    {
        proxy.setSuperclass(clz);
        proxy.setCallback(this);
        return proxy.create();
    }
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("用户鉴权");
        methodProxy.invokeSuper(o,objects);
        return null;
    }
}

测试类

package com.lee.aop.cglib;
/**
 * @author lee
 */
public class Tester {
    public static void main(String[] args) {
        UserProxy proxy = new UserProxy();
        UserService userService = (UserService) proxy.getProxy(UserService.class);
        userService.updateUser("lee");
    }
}

JDK动态代理与CGlib代理的区别

  • JDK动态代理只能对实现了接口的类生成代理,而不能针对类
  • CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法(继承)
  • JDK的动态代理是基于类实现了接口,cglib是基于类,没有强制要求目标类一定要是实现接口。
  • JDK的核心是实现InvocationHandler接口,使用invoke()方法进行面向切面的处理,调用相应的通知。
  • CGLIB的核心是实现MethodInterceptor接口,使用intercept()方法进行面向切面的处理,调用相应的通知。

所以在Spring中当Bean实现接口时,Spring就会用JDK的动态代理,当Bean没有实现接口时,Spring使用CGlib来实现。

到此这篇关于深入了解SpringAOP中的jdk动态代理与CGlib的文章就介绍到这了,更多相关jdk动态代理与CGlib内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java删除Word文档中水印的实现方法

    Java删除Word文档中水印的实现方法

    在 Word 文档中,水印常用于标示文档的状态,但可能会影响文档的清晰度和专业性,本文将介绍如何使用 Java 删除 Word 文档中的水印,有需要的可以了解下
    2025-11-11
  • 浅谈在Spring中如何使用数据源(DBCP、C3P0、JNDI)

    浅谈在Spring中如何使用数据源(DBCP、C3P0、JNDI)

    这篇文章主要介绍了浅谈在Spring中如何使用数据源(DBCP、C3P0、JNDI),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-10-10
  • Arthas排查Kubernetes中应用频繁挂掉重启异常

    Arthas排查Kubernetes中应用频繁挂掉重启异常

    这篇文章主要为大家介绍了Arthas排查Kubernetes中应用频繁挂掉重启的异常分析,有需要的朋友可以借鉴参考下,希望能够有所帮助祝大家多多进步
    2022-02-02
  • Spring反射内置工具类ReflectionUtils用法及说明

    Spring反射内置工具类ReflectionUtils用法及说明

    这段文章主要介绍了Java反射机制及其在获取sentinel熔断规则map和操作类属性方法中的应用,通过JDK和Spring的ReflectionUtils展示了如何优雅地处理反射操作,提升代码的可阅读性和维护性
    2026-06-06
  • 详解Java中Dijkstra(迪杰斯特拉)算法的图解与实现

    详解Java中Dijkstra(迪杰斯特拉)算法的图解与实现

    Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径。本文将详解该算法的图解与实现,需要的可以参考一下
    2022-05-05
  • 基于重定向RedirectAttributes的用法解析

    基于重定向RedirectAttributes的用法解析

    这篇文章主要介绍了基于重定向RedirectAttributes的用法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • idea同步yapi插件的详细步骤

    idea同步yapi插件的详细步骤

    yapi是一个很好的接口文档维护工具,其swagger功能,可将接口信息同步到yapi平台上,这篇文章主要介绍了idea同步yapi插件,需要的朋友可以参考下
    2024-04-04
  • springboot redis使用lettuce配置多数据源的实现

    springboot redis使用lettuce配置多数据源的实现

    这篇文章主要介绍了springboot redis使用lettuce配置多数据源的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • java中的switch case语句使用详解

    java中的switch case语句使用详解

    这篇文章主要介绍了java中的switch case语句使用详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-07-07
  • SpringBoot如何使用TestEntityManager进行JPA集成测试

    SpringBoot如何使用TestEntityManager进行JPA集成测试

    TestEntityManager是Spring Framework提供的一个测试框架,它可以帮助我们进行 JPA 集成测试,在本文中,我们将介绍如何使用 TestEntityManager 进行 JPA 集成测试,感兴趣的跟着小编一起来学习吧
    2023-06-06

最新评论