设计模式-代理模式

设计模式目录:https://blog.youkuaiyun.com/qq_52681418/article/details/114828850

设计模式-代理模式

代理模式代理一个类,不修改类而增加类的功能。

几种代理模式的比较

  • jdk静态代理:需要类、代理器类必须继承同一个接口。
  • jdk动态代理:需要类、代理器类都必须继承接口(不同一个)。
  • cglib动态代理:代理器继承接口。

1.静态代理

你有一个类已经写好了,不能修改了,你想扩展它该怎么办呢?

你在写这个类的时候,让它继承一个接口,然后创建一个代理器,代理器管理这个类并添加更多的功能。

1.这是你写好的类继承的接口(或继承抽象类)

public interface ParentInterFace {
    void show();
}

2.这是你的类

public class Goods implements ParentInterFace {
    public void show() {
        System.out.println("这是一个不能修改的类");
    }
}

3.创建一个代理器,代理器需要指定代理的目标,因此传入,并且代理器实现目标类实现的接口

public class Poxy implements ParentInterFace {

    protected ParentInterFace goods;

    public Poxy(ParentInterFace goods) {
        this.goods = goods;
    }

    //代理
    public void show() {
        System.out.println("---执行前扩展");
        goods.show();
        System.out.println("---执行后扩展");
    }
}

启动代理步骤

public class Main {
   public static void main(String[] args) {
       ParentInterFace goods  = new Goods();        //创建一个类
       ParentInterFace goods2 = new Poxy(goods);    //代理该类
       goods2.show();//输出结果
   }

}

结果
在这里插入图片描述
代理模式和装饰者模式很像,装饰者模式类为代理器创建子类,由子类扩展

这样做需要代理类、目标类都实现同一个接口或继承同一个抽象类,但有时候我们不想让它们继承同一个接口,我们如何代理呢?

此时我们就需要jdk动态代理、cglib来实现


2.JDK动态代理

代理器实现 InvocationHandler 接口

1.你的接口:必须有接口,只不过代理器不用实现

public interface ParentInterFace {
    void show();
}

1.一个普通类

public class Goods implements ParentInterFace{
    public void show() {
        System.out.println("这是一个类");
    }
}

2.代理器:实现InvocationHandler 接口,并实现invoke方法,在此方法中进行代理

public class Poxy implements InvocationHandler {
    
    protected ParentInterFace goods;
    //传入目标类
    public Poxy(ParentInterFace goods) {
        this.goods = goods;
    }

    //继承的调用器(实现代理)
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException {
        System.out.println("---执行前扩展");
        Object invoke=method.invoke(goods,args);
        System.out.println("---执行后扩展");
        return invoke;
    } 
}

invoke实际上通过反射调取对象的方法。

开始代理

public class Main {
   public static void main(String[] args) {
       ParentInterFace goods=new Goods();      //创建一个类
       InvocationHandler poxy=new Poxy(goods); //代理
       
       ClassLoader classLoader=poxy.getClass().getClassLoader();//获取代理类的类加载器
       Class<?>[] classes=goods.getClass().getInterfaces();     //获取目标类实现的接口
       ParentInterFace goods2= (ParentInterFace) Proxy.newProxyInstance(classLoader,classes,poxy);//创建jdk代理对象
       goods2.show();
   }
}

结果
在这里插入图片描述

3.CGlib动态代理

可在运行期扩展java类和实现java接口,底层通过使用字节码处理框架ASM,来转换字节码并生成新的类。

  • spring的AOP就是使用cglib动态代理实现的。
  • Hibernate用它来实现PO(Persistent Object 持久化对象)字节码的动态生成。

cglib是一个工具,使用它你需要引入依赖:maven依赖如下

<dependency>
      <groupId>net.sourceforge.cglib</groupId>
      <artifactId>com.springsource.net.sf.cglib</artifactId>
      <version>2.1.3</version>
</dependency>

cglib是通过构建目标类的子类,然后子类拦截父类方法来实现代理的。使用cglib,目标类不需要继承接口。

1.你的类

public class Goods{
    public void show() {
        System.out.println("这是一个类");
    }
}

2.代理类,继承接口MethodInterceptor

默认情况会代理Goods的全部方法,你可在这里添加一条判断来决定代理哪些方法。

public class Poxy implements MethodInterceptor {
    //代理方法
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("---扩展了方法---:"+method.getName());
        System.out.println("---执行前扩展");
        Object invoke=methodProxy.invokeSuper(o,objects);
        System.out.println("---执行后扩展");
        return invoke;
    }
}

方法的返回值不知道是什么,没法获取该对象的类,返回null也不影响正常代理

开始代理

public class Main {
    public static void main(String[] args) {
        Enhancer enhancer=new Enhancer();
        enhancer.setSuperclass(Goods.class);    //继承目标类
        enhancer.setCallback(new Poxy());       //设置回调
        Goods goods= (Goods) enhancer.create(); //获取goods
        goods.show();
    }
}

实现:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值