专业

深圳网站优化客服热线:SEO

揭秘百度SEO快排7天上首页秘籍详情

深圳网站优化

当前位置:首页 > 技术教程

细说代理模式 - 贪挽懒月的个人空间 - OSCHINA

来源: 作者: 访问次数:16

细说代理模式

贪挽懒月
 贪挽懒月 发布于 前天 18:55
字数 1623
阅读 662
收藏 0
点赞 0
评论 0
javacglib

#2020云栖大会#阿里云海量offer来啦!投简历、赢阿里云限量礼品及阿里云ACA认证免费考试资格!>>>

代理模式,大家应该都不陌生,很多框架底层都用了代理模式,像spring、mybatis等。虽然大家都听说过代理模式,但是可能也并不是那么地了解,本文将说一下常用的代理模式。

一、代理模式介绍

代理模式其实就是找替身,要去办一件事儿,自己不去,找人代替你去,这就是代理模式。在程序中就是,为对象提供一个替身,控制替身去访问目标对象,这样做的好处是,除了目标对象能提供的功能外,还可以让替身多做一些活,即可以扩展目标对象的功能。被代理的可以是远程对象、创建时开销很大的对象或者需要安全控制的对象。

代理模式主要分为以下三种:

  • 静态代理
  • 动态代理(又叫JDK代理、接口代理)
  • cglib代理(也属于动态代理的范畴)

二、静态代理

「1、静态代理介绍:」

使用静态代理的时候,需要定义接口或者父类,被代理的对象和代理对象需要一起实现相同的接口或者继承相同的父类。

「2、应用实例:」

  • 定义一个接口: TeacherDao
  • 定义被代理的对象: TeacherDaoImpl,需要实现 TeacherDao
  • 定义代理对象: TeacherDaoProxy,也需要实现 TeacherDao
  • 要调用 TeacherDaoImpl方法时,需要先创建 TeacherDaoProxy对象,然后创建 TeacherDaoImpl对象,将 TeacherDaoImpl对象交给 TeacherDaoProxy对象,再调相关方法

代码实现:

  • TeacherDao.java:
public interface TeacherDao {
    void teach();
}
  • TeacherDaoImpl.java:
public class TeacherDaoImpl implements TeacherDao {
    @Override
    public void teach() {
        System.out.println("今天又是没妹子的一天(ノへ ̄、)");
    }
}
  • TeacherDaoProxy.java:
public class TeacherDaoProxy implements TeacherDao {
    
    private TeacherDao target; // 被代理的对象
    
    public TeacherDaoProxy(TeacherDao target){
        this.target = target;
    }
    
    @Override
    public void teach() {
        System.out.println("代理开始");
        // 这里可以写一些额外的逻辑,以达到扩展被代理对象的目的,相当于spring的前置通知
        target.teach();
        // 这里也可以写一些额外的逻辑,以达到扩展被代理对象的目的,相当于spring的后置通知
        System.out.println("代理结束");
    }
}
  • Client.java:调用代理对象
public class Client {

    public static void main(String[] args){
        // 创建被代理的对象
        TeacherDao target = new TeacherDaoImpl();
        // 创建代理对象
        TeacherDaoProxy proxy = new TeacherDaoProxy(target);
        // 通过代理对象调用方法
        proxy.teach();
    }
}

「3、静态代理的优缺点:」

  • 优点:可以在不修改被代理对象的前提下扩展被代理的对象,做一些增强
  • 缺点:需要实现相同的接口或者继承相同的父类,所以代理类会很多,而且如果接口或者父类有改动,代理对象和被代理对象都需要维护

三、动态代理(JDK代理)

「1、动态代理介绍:」

代理对象不要实现接口,但是被代理对象还是需要实现接口的。动态代理对象的生成,利用的是JDK的API,反射包下的Proxy类,动态地在内存中构建代理对象。

「2、java.lang.reflect.Proxy:」

这个类有一个newProxyInstance方法,该方法接收三个参数,如下:

static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)

「3、应用实例:」

  • 定义一个接口:TeacherDao
  • 定义被代理的对象:TeacherDaoImpl,需要实现TeacherDao
  • 定义一个代理工厂ProxyFactory,有一个getProxyInstance方法,需要传入被代理的对象,然后返回代理对象实例,通过代理对象调用被代理对象的方法

代码实现:

  • TeacherDao.java:
public interface TeacherDao {
    void teach();
}
  • TeacherDaoImpl.java:
public class TeacherDaoImpl implements TeacherDao {
    @Override
    public void teach() {
        System.out.println("今天又是没妹子的一天(ノへ ̄、)");
    }
}
  • ProxyFactory.java
public class ProxyFactory {

    private Object target; // 被代理的对象

    public ProxyFactory(Object target){
        this.target = target;
    }

    // 给被代理的对象生成一个代理对象
    public Object getProxyInstance(){
        // 参数1:指定被代理对象的类加载器
        // 参数2:被代理对象实现的接口类型
        // 参数3:事件处理,执行被代理对象的方法
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("JDK代理开始");
                // 调用方法,args的方法的参数
                Object returnValue = method.invoke(target, args);
                System.out.println("JDK代理结束");
                // 将执行结果return
                return returnValue;
            }
        });
    }
}
  • Client.java:通过代理调用方法
public class Client {

    public static void main(String[] args){
        // 创建被代理的对象
        TeacherDao target = new TeacherDaoImpl();
        // 创建代理对象
        TeacherDao proxy = (TeacherDao) new ProxyFactory(target).getProxyInstance();
        // 通过代理对象调用被代理对象的方法
        proxy.teach();
    }
}

四、cglib代理

「1、cglib代理介绍:」

静态代理和动态代理,被代理的对象,都需要实现接口,如果一个类没实现任何接口的,那就要用cglib代理了。cglib代理也叫子类代理,它会在内存中构建一个子类对象,从而实现对被代理对象的扩展。cglib代理底层是通过一个叫ASM的字节码处理框架来转换字节码并生成新的类从而实现代理的。被代理的类不能为final,否则会报错。被代理对象的方法如果是final/static,就不会被拦截,即不会执行被代理对象额外的业务方法。

「2、应用实例:」

  • 首先要添加cglib相关依赖:
<dependency>
     <groupId>cglib</groupId>
     <artifactId>cglib</artifactId>
     <version>3.3.0</version>
</dependency>
  • TeacherDaoImpl.java:
public class TeacherDaoImpl implements TeacherDao {
    @Override
    public void teach() {
        System.out.println("今天又是没妹子的一天(ノへ ̄、)");
    }
}
  • CglibProxyFactory.java:
// 需要实现MethodInterceptor并重写其方法
public class CglibProxyFactory implements MethodInterceptor {

    private Object target;

    public CglibProxyFactory(Object target){
        this.target = target;
    }

    /**
     * 返回target的代理对象
     * @return
     */
    public Object getProxyInstance(){
        // 1. 创建工具类
        Enhancer enhancer = new Enhancer();
        // 2. 设置父类
        enhancer.setSuperclass(target.getClass());
        // 3. 设置回调函数
        enhancer.setCallback(this);
        // 4. 创建子类对象,即代理对象
        return enhancer.create();
    }
    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("CGLIB代理开始");
        Object returnValue = method.invoke(target, args);
        System.out.println("CGLIB代理结束");
        return returnValue;
    }
}
  • Client.java:通过代理调用方法
public class Client {

    public static void main(String[] args){
        // 创建被代理的对象
        TeacherDaoImpl target = new TeacherDaoImpl();
        // 获取代理对象,并将被代理对象传给代理对象
        TeacherDaoImpl proxy = (TeacherDaoImpl) new CglibProxyFactory(target).getProxyInstance();
        // 执行方法,触发intecept方法,从而实现执行被代理对象的方法
        proxy.teach();
    }
}



-java开发那些事-
长按扫描二维码
关注我 获取更多内容
分享、点赞、在看三连


本文分享自微信公众号 - java开发那些事(javawebkf)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

  • 全面实用的SEO竞争对手研究
  • seo优化逻辑和品牌如何进行口碑建设
  • 「飞优seo」手把手教你如何安装宝塔面板
  • 移动端SEO优化应该注意的几点
  • 你不知道的SEO常见术语,万词霸屏带你深入了解!
  • seo如何获取长尾流量
  • 企业网站建设seo优化如何写好软文
  • SEO优化案例中常犯的7个错误
  • SEO需要抛弃老旧观点才能跟上节奏
  • SEO优化对一个企业的影响力有多大
  • 让您的网站提升排名的SEO四步策略
  • 单页网站怎么做SEO优化与推广
  • 评价分析、FB兴趣发现、客户管理、SEO相关,我们推荐这50个工具
  • 想让网站流量翻倍,那你会做seo优化吗
  • SEO搜索优化,你可以不做外链吗?
  • seo软文写作必备知识
  • 杭州优化公司教你怎样通过SEO做产品宣传推广?
  • 网站SEO标题规划操作,网页标题修改后应该怎么办?
  • 2020年10个步骤让你从SEO小白到专家
  • 企业网站建设seo优化排名不稳定是什么原因?
  • SEO优化|如何判断是否过度优化 爱帮网络总结五点
  • 当心SEO优化行业中的伪科学
  • SEO指南:学习如何对网站进行SEO
  • SEO常用的关键词扩展分析工具有哪些?
  • 新手SEO需要学习十大要点我们相信许多企业都知道SEO优化是非常重要的,当他们第一次进入互联网。他们希望通过搜索引擎的免费频道获得大量流量。那么如何学习搜索引擎优化呢?这里我们给你一些建议。 1、准备空间和域名 SEO有很多概念术语,当然,这些都是要记住的,但不建议死记硬背,而是在实践中(操作网站优化时)要记住,因为死记硬背很容易忘记,而且你也不会真正理解它的含义。因此,我们主张我们应该从学习SEO的第一天开始操作。学习SEO一定要实践,即使你学了2年SEO课程,如果你没有实践过,你只会成为SEO的理
  • 有效SEO优化攻略已备好,咨询、转化不再“愁”
  • SEO网站诊断怎么做?几点基本因素和大家分享
  • SEO指南:学习如何对网站进行SEO
  • 如何做好seo优化内链工作
  • 如何做好seo优化内链工作
  • 网站改版的SEO注意事项!
  • 网站SEO课程笔记整理版!
  • 外贸网站优化所需采用的SEO策略
  • 百度SEO优化,什么时间增加内容与反向链接?
  • SEO网站数据分析调整
  • 雇佣SEO公司前请尝试15个SEO技巧
  • 关于网站seo的几点小常识,你知道多少?
  • SEO内容策划和文案是根基
  • 什么是SEO文章?seo文章的作用方法
  • SEO优化外包公司该怎么选?