栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

java设计模式之代理模式

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

java设计模式之代理模式

下面先来说静态代理:

先来看一下UML关系图:

话不多说,直接看代码:

先看一下整体UML关系图

先来看IBuyHouse接口:

package pxx.staticproxy;

//做一个静态代理
public interface IBuyHouse {
    void buyHouse();
}

再来看被代理对象,也就是目标对象ZhangSanBuyHouse

package pxx.staticproxy;

public class ZhangSanBuyHouse implements IBuyHouse{

    @Override
    public void buyHouse() {
        System.out.println("我是张三,我要准备房子了");
    }

}

 然后来看代理对象BuyHouseProxy

package pxx.staticproxy;

public class BuyHouseProxy implements  IBuyHouse {

    //聚合一个被代理对象在里面(目标对象)
    IBuyHouse buyHouse;

    public BuyHouseProxy(IBuyHouse buyHouse) {
        this.buyHouse = buyHouse;
    }
    @Override
    public void buyHouse() {
        System.out.println("我想要一个105平方的大房子");
        buyHouse.buyHouse();
        System.out.println("我付完了钱,已经买了房子了");
    }
}

最后来看客户端的测试文件

package pxx.staticproxy;

public class Test {
    public static void main(String[] args) {
        //这里面实现两个类对象
        //给代理对象传一个被代理对象进去
        BuyHouseProxy buyHouseProxy = new BuyHouseProxy(new ZhangSanBuyHouse());
        buyHouseProxy.buyHouse();
    }
}

运行结果:

上面就把张三要代理买房子给做完了,那么假设现在李四也要来代理买房子

添加一个李四类

package pxx.staticproxy;

public class LiSiBuyHouse implements IBuyHouse {
    @Override
    public void buyHouse() {
        System.out.println("我是李四,我也要买房子了");
    }
}

然后在Test里面实现一个李四对象:

 

这么一看,静态代理也是可以实现多个用户进行代理啊,但是如果我不想代理买房子这个对象呢,我假如要代理 买鞋呢,那么我们又要开一个代理类,这样下去我们就会开很多代理类来做这件事儿,还有一个问题是,一旦接口增加方法,目标对象与代理对象就要维护。

下面说一下动态代理:

下面先来说JDK代理:

大致步骤:

1.目标对象实现接口,传入到代理对象里面

2.利用反射,Proxy类的newProxyInstance方法自动给我们创建一个代理对象

3.然后通过代理对象,调用目标对象的方法

先来看类图:

先来看IBuyShoes接口:

package pxx.dynamic;

public interface IBuyShoes {
    public void buyShoes();
}

 再来看目标对象ZhangSanBuyShoes

package pxx.dynamic;

import pxx.staticproxy.IBuyHouse;

//目标对象必须实现一个接口
public class ZhangSanBuyShoes implements IBuyShoes {
    @Override
    public void buyShoes() {
        System.out.println("我是张三,我要准备买鞋");
    }
}

在来看一个代理类ProxyFactory

package pxx.dynamic;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

//因为这个可以代理很多年对象
//所以直接就可以当成一个代理工厂
public class ProxyFactory {
    //维护一个目标对象,这是一个Objet类型可以接收任何类型
    private Object target;


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

    //给目标对象动态生成一个代理对象
    public Object getProxyInstance() {
        //利用反射里面一个类Proxy调用newProxyInstance方法
        
        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("代理开始");
                        Object res = method.invoke(target,args);
                        System.out.println("代理结束");
                        return res;
                    }
                });
    }
}

然后看一个测试类Test

package pxx.dynamic;

import pxx.staticproxy.IBuyHouse;
import pxx.staticproxy.ZhangSanBuyHouse;

public class Test {
    public static void main(String[] args) {
        //创建目标对象
        IBuyShoes target = new ZhangSanBuyShoes();
        //然后调用方法,给目标对象创建一个代理对象
        //注意返回的是Object方法
        IBuyShoes proxyInstance = (IBuyShoes)new ProxyFactory(target).getProxyInstance();
        //然后通过代理对象调用目标对象的方法
        proxyInstance.buyShoes();
    }
}

 运行结果

上面就解决了我们如果更改被代理对象需要创建多个代理类的问题,而且还能改变,我们如果需要在被代理类里面创建一个方法,需要在代理类里面创建多个方法 的问题。比如我们我们在添加一个代理方法

又比如在添加一个买衣服的方法

然后代理类完全不用改动直接代理就行了

 

上面就是JDK代理。

下面说一下Cglib代理:

前面两种代理,有一个共同点,就是要求目标对象实现一个接口,但是有时候目标对象就是一个单独对象,没有实现任何接口,这个时候我们可以使用目标对象的子类来实现代理

因为Cglib是由一系列包组成的,那么我们就要引入Cglib的jar包文件

 

 

这里再说一下两个额外注意的问题:

1.在内存中动态构建子类,不能为final,因为final类基本上来说,就是啥也干不了

2.如果目标对象方法为final/static,你不会被执行

说一下cglib大致流程:

1.实现MethodInterceptor类,利用一系列固定操作来生成一个target目标对象的子类

2. 重写intecpet方法,这个方法会当代理对象执行被代理对象方法时被触发,然后调用目标对象

 话不多说,直接上代码:

先来看一下UML关系图 

 先来看一个被代理对象:

ZhangSanBuyShoes

package pxx.cglib;

//这个用户就不需要去实现接口
public class ZhangSanBuyShoes {
    public void buyShoes() {
        System.out.println("我是张三,我要买鞋");
    }
}

再来看代理类ProxyFactory

package pxx.cglib;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

//我们必须去实现一个方法拦截器接口
public class ProxyFactory implements MethodInterceptor {

    //依旧是维护一个目标对象
    private Object target;

    //传入一个被代理的对象
    public ProxyFactory(Object target) {
        this.target = target;
    }

    //还要得到一个代理对象的方法
    //也就是返回当前目标的代理对象
    public Object getProxyInstance() {
        //1.创建工具类(固定,在cglib包里面)
        Enhancer enhancer =  new Enhancer();
        //2.设置父类(固定),传递被代理对象的class字节码文件
        enhancer.setSuperclass(target.getClass());
        //3.设置回掉函数(固定)
        enhancer.setCallback(this);//传入的当前这个代理对象
        //4.创建子类对象,即代理对象(固定)
        return enhancer.create();
    }

    //这个方法就会帮我们去调用目标对象的方法,触发实现
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("我需要43码的鞋");
        //调用目标对象的方法,传入目标对象与参数
        Object res = method.invoke(target,objects);
        System.out.println("我已经买好鞋了");
        return res;
    }
}

看Test

package pxx.cglib;

import com.sun.deploy.uitoolkit.impl.fx.AppletStageManager;

import java.util.Properties;

public class Test {
    public static void main(String[] args) {
        ZhangSanBuyShoes target = new ZhangSanBuyShoes();
        //传递给代理对象
        ZhangSanBuyShoes proxyFactory =(ZhangSanBuyShoes) new ProxyFactory(target).getProxyInstance();
        //执行代理对象的方法,触发intecept方法,然后实现目标对象调用
        proxyFactory.buyShoes();
    }
}

运行结果

好了,代理模式大致就说到这吧 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/838711.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号