前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java中的代理模式

Java中的代理模式

作者头像
Java学习录
发布2019-08-08 17:22:14
4650
发布2019-08-08 17:22:14
举报
文章被收录于专栏:Java学习录Java学习录

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

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

为什么要使用代理模式

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

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

静态代理

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

代码语言:javascript
复制
public interface MainService {
    void doSomeThing();
}
public class MainServiceImpl implements MainService {
    public void doSomeThing() {
        System.out.println("doSomeThing......");
    }
}

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

代码语言:javascript
复制
public void doSomeThing() {
    System.out.println("begin time:"+System.currentTimeMillis());
    mainService.doSomeThing();
    System.out.println("end time:"+System.currentTimeMillis());
}

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

代码语言:javascript
复制
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());
    }
}

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

代码语言:javascript
复制
public static void main (String args[]){
       MainService mainService=new MainServiceImpl();
       MainService staticProxy=new StaticProxy(mainService);
       staticProxy.doSomeThing();
   }
动态代理

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

代码语言:javascript
复制
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方法是返回的一个代理对象,切是在这个对象的所有方法执行前后都执行了打印执行时间的逻辑 看一下测试代码

代码语言:javascript
复制
public static void main (String args[]){
       MainService mainService=new MainServiceImpl();
       DynamicProxy dynamicProxy=new DynamicProxy(mainService);
       ((MainService)dynamicProxy.getProxy()).doSomeThing();
   }

这样就优雅的多了

Cglib代理

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

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

代码语言:javascript
复制
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;
    }
}

看一下测试代码

代码语言:javascript
复制
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();
   }
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-08-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java学习录 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 为什么要使用代理模式
  • 静态代理
  • 动态代理
  • Cglib代理
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档