Java中的代理模式

妖狐艹你老母 2024-04-18 20:38 52阅读 0赞

代理模式:通过某种方式给某个对象提供一个代理对象,在不改变原有对象代码的前提下对方法的增强。

在Java中我们最熟悉的使用场景就是SpringAOP,本篇文章即是SpringAOP源码分析的前置文章

为什么要使用代理模式

首先我们知道,在项目中如果需要打印方法入参及出参时、需要记录方法执行时间时、需要验证权限时、需要统一异常处理时等等各种场景是不是都是使用拦截器呀过滤器呀啥的。
这些拦截器过滤器的底层实现其实都是使用了代码模式

本篇文章就基于一个打印方法执行时间的小demo来简单了解一下代理模式的使用

静态代理

首先有一个接口和一个实现类








  1. 1
    2
    3
    4
    5
    6
    7
    8
  1. public interface MainService {

    void doSomeThing();
    }
    public class MainServiceImpl implements MainService {

    public void doSomeThing() {

    System.out.println(doSomeThing……”);
    }
    }

当我们想要知道doSomeThing方法的执行时间时比较low的解决方案可能就是这样搞








  1. 1
    2
    3
    4
    5
  1. public void doSomeThing() {

    System.out.println(begin time:”+System.currentTimeMillis());
    mainService.doSomeThing();
    System.out.println(end time:”+System.currentTimeMillis());
    }

但是这样就不能实现不修改代码就处理问题的初衷了,这个时候就可以使用静态代理来解决








  1. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
  1. public class StaticProxy implements MainService {

    private MainService mainService;
    public StaticProxy(MainService mainService){

    this.mainService=mainService;
    }
    public void doSomeThing() {

    System.out.println(begin time:”+System.currentTimeMillis());
    mainService.doSomeThing();
    System.out.println(end time:”+System.currentTimeMillis());
    }
    }

这里创建的了一个代理类,代理类持有原对象,把所有新增的需求放到代理类中,这样就不需要修改代码了。
我们可以使用如下代码测试








  1. 1
    2
    3
    4
    5
  1. public static void main (String args[]){

    MainService mainService=new MainServiceImpl();
    MainService staticProxy=new StaticProxy(mainService);
    staticProxy.doSomeThing();
    }
动态代理

上方使用静态代理虽然解决了不修改代码的需求,但是如果原对象有多个方法的话就必须全部实现且加上打印的逻辑,这样就有点不太优雅了吧
这个时候就到了动态代理出场的时候了








  1. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
  1. public class DynamicProxy {

    private MainService mainService;
    public DynamicProxy(MainService mainService){

    this.mainService=mainService;
    }

    public Object getProxy() {

    return Proxy.newProxyInstance(
    mainService.getClass().getClassLoader(),
    mainService.getClass().getInterfaces(),
    new InvocationHandler() {

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

    System.out.println(begin time:”+System.currentTimeMillis());
    method.invoke(mainService, args);
    System.out.println(end time:”+System.currentTimeMillis());
    return null;
    }
    });
    }
    }

可以看到上方的getProxy方法是返回的一个代理对象,切是在这个对象的所有方法执行前后都执行了打印执行时间的逻辑
看一下测试代码








  1. 1
    2
    3
    4
    5
  1. public static void main (String args[]){

    MainService mainService=new MainServiceImpl();
    DynamicProxy dynamicProxy=new DynamicProxy(mainService);
    ((MainService)dynamicProxy.getProxy()).doSomeThing();
    }

这样就优雅的多了

Cglib代理

动态代理实现的已经非常优雅了,但是它还是有个缺点,那就是想要实现代理的原对象必须具有顶层接口,对没有实现的接口的类就无能为力了。

不过记住一句话,方法总比困难多。对于这种没有接口的类使用cglib代理就可以解决它。
与动态代理创建一个代理类不同的是cglib是使用字节码技术直接生成一个子类然后重写父类的方法








  1. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
  1. public class CglibInterceptor implements MethodInterceptor {



    public Object intercept(Object obj, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {

    System.out.println(begin time:”+System.currentTimeMillis());
    Object object = methodProxy.invokeSuper(obj, objects);
    System.out.println(end time:”+System.currentTimeMillis());
    return object;
    }
    }

看一下测试代码








  1. 1
    2
    3
    4
    5
    6
    7
  1. public static void main (String args[]){

    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(MainServiceImpl.class);
    enhancer.setCallback(new CglibInterceptor());
    MainService proxy= (MainService)enhancer.create();
    proxy.doSomeThing();
    }

640?wx\_fmt=gif

不得不看

1.SpringCloud系列博客汇总

2.为啥一线大厂面试必问Redis,有啥好问的?

3.Java多线程面试必备基础知识汇总

4.Java集合源码分析汇总

5.Linux常用命令汇总

6.JVM系列文章汇总

7.MySQL系列文章汇总

8.RabbitMQ系列文章汇总

640?wx\_fmt=jpeg

发表评论

表情:
评论列表 (有 0 条评论,52人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Java代理模式

    > 代理模式:通过某种方式给某个对象提供一个代理对象,在不改变原有对象代码的前提下对方法的增强。 在Java中我们最熟悉的使用场景就是SpringAOP,本篇文...

    相关 Java代理模式

    1.什么是代理模式 代理模式:就是为其他对象提供一种代理以控制对这个对象的访问。 代理可以在不改动目标对象的基础上,增加其他额外的功能(扩展功能)。 ![在这里插入

    相关 Java代理设计模式

    Java中的代理模式(proxy) > 代理是一种常用的设计模式,代理模式可以对原有的类进行扩展,即通过代理对象的模式来访问目标类。最通俗的例子就是假设我们想邀请一位明星,那

    相关 java代理模式

    简单来说代理模式就是通过一个代理对象去访问一个实际对象,并且可以像装饰模式一样给对象添加一些功能。 静态代理 所谓静态代理即在程序运行前代理类就已经存在,也就是说我们编...