Java:三种代理模式示例

什么是代理模式?

代理(Proxy)是一种设计模式,为其他对象提供一种代理以控制对这个对象的访问。

代理模式的组成

  • 抽象角色:通过接口或抽象类声明真实角色实现的业务方法。
  • 代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。
  • 真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。

代理模式的优点

(1).职责清晰

真实的角色就是实现实际的[业务逻辑,不用关心其他非本职责的事务,通过后期的代理完成一件完成事务,附带的结果就是编程简洁清晰。

(2).代理对象可以在客户端和目标对象之间起到中介的作用,这样起到了中介的作用和保护了目标对象的作用。

(3).高扩展性

代理模式的关键点是:代理对象与目标对象.代理对象是对目标对象的扩展,并会调用目标对象。

一、静态代理

步骤1:创建接口 Animal.java

复制代码
/**
 * 静态代理步骤1
 *  -创建接口
 * */
public interface Animal {

    void run();
    void eat();

}

步骤2:创建实现类并实现步骤1的接口 AnimalImpl.java

复制代码
/**
 * 静态代理步骤 2
 *  -创建实现类并实现步骤1的接口
 * */
public class AnimalImpl implements Animal{

    @Override
    public void run() {
        System.out.println("猎豹跑的都很快");
    }

    @Override
    public void eat() {
        System.out.println("动物为了生存,一般都喜欢进食");
    }
}

步骤3:创建代理类并实现步骤1的接口 StaticProxy.java

复制代码
/**
 * 静态代理步骤 3
 *  -创建代理类并实现步骤1的接口
 * */
public class StaticProxy implements Animal{

    private Animal animal;// 目标对象

    // 构造函数
    StaticProxy(){}

    StaticProxy(Animal _animal){
        this.animal = _animal;
    }

    @Override
    public void run() {
        System.out.println("事物开始前");
        animal.run();
        System.out.println("事物开始后");
    }

    @Override
    public void eat() {
        System.out.println("事物开始前");
        animal.eat();
        System.out.println("事物开始后");
    }
}

步骤4:实现代理方法:

复制代码
/**
 * 静态代理步骤4
 *  -实现静态代理方法
 * */
public class TestMain {
    /**
     * 总结:
     *
     * 静态代理在使用时,需要定义接口或者父类,被代理对象与代理对象一起实现接口或继承相同 的父类
     * 缺点:
     *
     * 因为代理对象需要和被代理对象实现相同的接口或父类,所以会有太多的代理类
     * 一旦接口中增加了方法后,被代理对象和代理对象都需要维护(非常麻烦,不方便)
     * */
    public static void main(String[] args) {
        //1.创建目标对象(通过目标实现类创建目标对象)
        Animal animal = new AnimalImpl();

        //2.创建代理对象(将目标对象传递进代理对象,建立代理关系)
        StaticProxy staticProxy = new StaticProxy(animal);

        //3.执行方法
        staticProxy.run();
        staticProxy.eat();
    }

运行结果:

二、JDK动态代理

步骤1:创建接口 Persion.java

复制代码
/**
 * JDK动态代理步骤1
 *  -创建接口
 * */
public interface Persion {

    void say();

}

步骤2:创建实现类并实现步骤1的接口PersionImpl.java

复制代码
/**
 * JDK动态代理步骤2
 *  -创建实现类并实现步骤1的接口
 * */
public class PersionImpl implements Persion {
    @Override
    public void say() {
        System.out.println("每个人都有说话的权力!");
    }
}

步骤3:创建动态代理类JDKProxy.java

复制代码
/**
 * JDK动态代理步骤3
 *  -创建动态代理类
 * */
public class JDKProxy {

    private Persion persion;// 目标对象

    // 构造函数
    public JDKProxy(Persion _persion){
        this.persion = _persion;
    }


    /**
     *  给目标对象生成代理对象
     *
     * JDK中动态代理类只需要使用java.lang.reflect.Proxy.newProxyInstance方法,该方法需要接收三个参数,完整写法:
     * static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h)
     *
     * ClassLoader loader:指定当前目标对象使用类加载器,获取加载器的方法是固定的
     * Class<?>[] interfaces:目标对象实现的接口类型,使用泛型方式确认类型,获取接口类型的方法是固定的
     * InvocationHandler h;事件处理,执行目标对象的方法时,会触发事件处理器的方法,会把当前执行目标对象的方法作为参数传入
     * */
    public Object getProxyInstance(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),persion.getClass().getInterfaces(),this::invoke);
    }


    /**
     * 生成执行目标对象方法
     * */
    public Object invoke(Object proxy, Method method, Object[] args){
        try{
            System.out.println("开始事务");
            //执行目标对象方法
            Object returnValue = method.invoke(persion, args);
            System.out.println("结束事务");
            return returnValue;
        }catch (Throwable  throwable){
            throwable.getLocalizedMessage();
            return null;
        }

    }
}

步骤4:实现代理方法

复制代码
/**
 * JDK动态代理步骤4
 *  -实现代理方法
 *
 *  测试jdk动态代理
 *      代理对象不需要实现接口,但是目标对象一定要实现接口,否则不能用动态代理
 *      接口中增加方法时只用在实现类中增加方法,不用修改代理类。
 * */
public class JDKMain {

    public static void main(String[] args) {
        // 目标对象
        Persion persion = new PersionImpl();
        // 【原始的类型 class com.jwt.demo.jdkdl.PersionImpl】
        System.out.println(persion.getClass());

        // 给目标对象,创建代理对象
        Persion jdkProxy = (Persion) new JDKProxy(persion).getProxyInstance();
        // class $JDKProxy   内存中动态生成的代理对象
        System.out.println(jdkProxy.getClass());

        // 执行代理方法
        jdkProxy.say();


    }

}

运行结果:

三、cglib动态代理

步骤1:引入jar包

复制代码
       <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>3.3.0</version>
        </dependency>

步骤2:创建被代理的类UserDao.java

复制代码
public class UserDao{
    public void getUser() {
        System.out.println("cglib动态代理:得到用户信息");
    }
    public void insertUser() {
        System.out.println("cglib动态代理:添加用户");
    }
}

步骤3:创建代理类CglibProxy.java

复制代码
/**
 * cglib动态代理
 *
 * */
public class CglibProxy implements MethodInterceptor {
    //维护目标对象
    private Object target;
    public CglibProxy (Object target) {
        this.target = target;
    }
    //给目标对象创建一个代理对象
    public Object getProxyInstance(){
        //1.工具类
        Enhancer en = new Enhancer();
        //2.设置父类
        en.setSuperclass(target.getClass());
        //3.设置回调函数
        en.setCallback(this);
        //4.创建子类(代理对象)
        return en.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy         
       methodProxy) throws Throwable {
        System.out.println("开始事务...");
        //执行目标对象的方法
        Object returnValue = method.invoke(target, objects);
        System.out.println("提交事务...");
        return returnValue;
    }
}

步骤4:实现代理方法

复制代码
public class CglibProxyMain {
    public static void main(String[] args) {
        //目标对象
        UserDao target = new UserDao();
        System.out.println(target.getClass());
        // 给目标对象,创建代理对象
        UserDao proxy = (UserDao) new Proxy03(target).getProxyInstance();
        System.out.println(proxy.getClass());
        proxy.getUser();//执行的是代理的方法
        proxy.insertUser();
    }
}

运行结果:

相关推荐
猷咪6 小时前
C++基础
开发语言·c++
IT·小灰灰6 小时前
30行PHP,利用硅基流动API,网页客服瞬间上线
开发语言·人工智能·aigc·php
快点好好学习吧6 小时前
phpize 依赖 php-config 获取 PHP 信息的庖丁解牛
android·开发语言·php
秦老师Q6 小时前
php入门教程(超详细,一篇就够了!!!)
开发语言·mysql·php·db
烟锁池塘柳06 小时前
解决Google Scholar “We‘re sorry... but your computer or network may be sending automated queries.”的问题
开发语言
是誰萆微了承諾6 小时前
php 对接deepseek
android·开发语言·php
vx_BS813306 小时前
【直接可用源码免费送】计算机毕业设计精选项目03574基于Python的网上商城管理系统设计与实现:Java/PHP/Python/C#小程序、单片机、成品+文档源码支持定制
java·python·课程设计
2601_949868366 小时前
Flutter for OpenHarmony 电子合同签署App实战 - 已签合同实现
java·开发语言·flutter
星火开发设计6 小时前
类型别名 typedef:让复杂类型更简洁
开发语言·c++·学习·算法·函数·知识
qq_177767377 小时前
React Native鸿蒙跨平台数据使用监控应用技术,通过setInterval每5秒更新一次数据使用情况和套餐使用情况,模拟了真实应用中的数据监控场景
开发语言·前端·javascript·react native·react.js·ecmascript·harmonyos