随笔 - 632  文章 - 17  评论 - 54  阅读 - 93万

Java代理模式(静态代理&动态代理)

一、概述

  定义:为其他对象提供一种代理,以控制这个对象的访问。

  代理模式的种类:静态代理和动态代理

二、静态代理

  ps:我们创建一个Book用于基础操作,再创建一个JavaBook用来代理Book类的功能。

  1.Book.java

1
2
3
4
5
6
7
8
9
10
11
12
package com.yw.reflectjavalib.proxy.staticproxy;
 
/**
 * 定义一个book实体
 * create by yangwei
 * on 2020-02-16 17:48
 */
public class Book {
    public void doWork() {
        System.out.println("读书");
    }
}

  2.JavaBook.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.yw.reflectjavalib.proxy.staticproxy;
 
/**
 * java实体
 * create by yangwei
 * on 2020-02-16 17:49
 */
public class JavaBook {
    private Book book;
 
    public JavaBook(Book book) {
        this.book = book;
    }
 
    public void doWork() {
        System.out.println("Java");
        book.doWork();
    }
}

  3.main方法测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.yw.reflectjavalib.proxy.staticproxy;
 
/**
 * 静态代理测试
 * create by yangwei
 * on 2020-02-16 17:47
 */
public class StaticProxyDemo {
    public static void main(String[] args) {
        Book book = new Book();
        //这里由于Javabook中有Book类的引用,所以JavaBook除了可以做自己的事情外,可以顺便把Book的工作给做了。
        //也就是JavaBook代理了Book了的所有功能。这就是静态代理,非常的简单。
        //通常这种模式也可以延伸成为装饰模式,即JavaBook把Book类给装饰的更强大了。
        JavaBook javaBook = new JavaBook(book);
        javaBook.doWork();
    }
}

  

三、动态代理

  在上面的例子中我们虽然使用JavaBook代理了Book类,但是仔细一想这样做是有问题的。例如:每一个类都需要有一个对应的Proxy类,随着类增多则代理类也会增加很多。下面介绍一种只需要一个代理类就能搞定的方法——动态代理。

   在java.lang.reflect包中有一个Proxy类。Proxy类的Proxy.newProxyInstance(ClassLoader,Class[] interfaces,InvocationHandler)方法可以将目标对象进行注入,并实现对目标对象的修改。

  参数介绍:

  1.ClassLoader classLoader 目标对象的classloader

  2.Class<?>[] interfaces 目标对象实现的接口类型

  3.InvocationHandler handler 一个实现了InvocationHandler的对象,通过构造方法把目标对象注入,并在这个自定义类中做一些自定义的操作。

下面通过一个简单的例子玩一下动态代理,加深对动态代理的理解。ps:输出水果的颜色。

  1.IFruits.java

  

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.yw.reflectjavalib.proxy.staticproxy.dnyproxy;
 
/**
 * 定义一个水果的接口
 * create by yangwei
 * on 2020-02-16 18:10
 */
public interface IFruits {
    /**
     * 水果的颜色
     */
    String getColor();
}

  

  2.Apple.java

1
2
3
4
5
6
7
8
9
10
11
12
package com.yw.reflectjavalib.proxy.staticproxy.dnyproxy;
 
/**
 * create by yangwei
 * on 2020-02-16 18:12
 */
public class Apple implements IFruits {
    @Override
    public String getColor() {
        return "红色";
    }
}

  

  3.MyInvocationHandler.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.yw.reflectjavalib.proxy.staticproxy.dnyproxy;
 
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
 
/**
 * create by yangwei
 * on 2020-02-16 18:13
 */
public class MyInvocationHandler implements InvocationHandler {
    private Object target;
 
    public MyInvocationHandler(Object obj) {
        this.target = obj;
    }
 
    @Override
    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
        System.out.print("水果的颜色:");
        return method.invoke(target, objects);
    }
}

  

  4.DnyProxyDemo.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package com.yw.reflectjavalib.proxy.staticproxy.dnyproxy;
 
import java.lang.reflect.Proxy;
 
/**
 * 动态代理测试
 * create by yangwei
 * on 2020-02-16 18:01
 */
public class DnyProxyDemo {
    /**
     * 动态代理
     *
     * @param args
     */
    public static void main(String[] args) {
        //创建一个Apple实例
        IFruits iFruits = new Apple();
        //动态代理Apple,代理后把代理对象返回,由于是面向接口编程,所以可以直接把返回结果转换为接口类型。
        //而MyInvocationHandler中已经对代理对象apple做了相关的操作。例如:加上了"水果的颜色"
        //所以打印出来的值为:水果的颜色为:红色
        //如果去掉代理类,那打印结果只能是:红色。
        //这就是动态带来的神奇之处,只要把目标代理对象传进去,就可以对目标代理对象做一些个性化的包装
        //动态代理相较于静态代理的优势是,我们不必为每一个对象都创建一个代理对象了。直接使用Proxy.newProxyInstance弄出来一个就OK了。
        IFruits object = (IFruits) Proxy.newProxyInstance(iFruits.getClass().getClassLoader(), iFruits.getClass().getInterfaces(), new MyInvocationHandler(iFruits));
        System.out.println(object.getColor());
    }
}

  以上就是动态代理的完整例子,在以上例子中,如果我们不使用动态代理,直接处处apple的颜色,只能得到“红色”。使用动态代理后会在水果颜色前面加上描述:“水果的颜色为:红色”,大家可以运行下试试,感受下。

posted on   飘杨......  阅读(186)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示