静态代理与动态代理

2019-12-08  本文已影响0人  Sheldonlv

简介

看了挺多关于代理方面的文章,这是我个人对代理的一些粗浅的理解。

代理模式是一种毕竟常见的设计模式。
就好比歌手要开展演唱会,背后会有一个经纪人帮忙接活动,时间安排等。
在这里,歌手就是提供服务的对象,而经纪人就是代理。
而代理又分为 静态代理动态代理

静态代理

组成结构:

  1. 接口类
  2. 接口对象
  3. 代理类
/**
 * 1.歌手接口
 */
public interface Singer {
    // 歌手有唱歌这么个天赋
    public void singsong();
}
/**
 * 2.歌手的实例化-对象(刘德华)
 */
public class LiuSinger implements Singer{

    @Override
    public void singsong(){
        System.out.println("刘德华-正在激情演唱歌曲XXX");
    }
}
package test2;

/**
 * 3.静态代理类
 * Created by Sheldon on 2019/11/5.
 */
public class SingerStaticProxy implements Singer{

    // 歌手这一成员变量
    private Singer singer;

    public SingerStaticProxy(Singer singer){
        this.singer = singer;
    }

    // 唱歌之前
    public void beforeSing(){
        System.out.println("布置会场ing");
    }

    // 唱歌之后
    public void afterSing(){
        System.out.println("清理会场ing");
    }

    @Override
    public void singsong(){
        // 调用之前的操作
        beforeSing();
        // 调用代理对象的操作
        singer.singsong();
        // 调用之后的操作
        afterSing();
    }

    // 测试方法
    public static void main(String[] args) {
        // 创建歌手对象
        Singer singer = new LiuSinger();
        // 创建代理对象
        SingerStaticProxy proxy = new SingerStaticProxy(singer);
        // 调用歌手操作
        proxy.singsong();
    }
}
静态代理测试

动态代理

区别

  1. 静态代理 通常只代理一个类,动态代理是代理一个接口下的多个实现类。
  2. 静态代理 事先知道要代理的是什么,而动态代理不知道要代理什么东西,只有在运行时才知道。
  3. 静态代理 由程序员创建代理类或特定工具自动生成源代码再对其编译。
  4. 动态代理 是实现 JDK 里的 InvocationHandler 接口的 invoke 方法,但注意的是代理的是接口,也就是你的业务类必须要实现接口,通过 Proxy 里的 newProxyInstance 得到代理对象。

AOP 便是通过动态代理实现的
一般通过以下固定的套路实现的。

方法一:

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

/**
 * 动态代理
 * Created by Sheldon on 2019/11/5.
 */
public class SingerDynamicProxy implements InvocationHandler {

    // 代理的对象
    private Object object;

    public SingerDynamicProxy(Object object){
        this.object = object;
    }

    // 唱歌之前
    public void beforeSing(){
        System.out.println("动态-布置会场ing");
    }

    // 唱歌之后
    public void afterSing(){
        System.out.println("动态-清理会场ing");
    }

    /**
     * 代理对象要执行的方法:{即真正需要执行的代理对象的业务方法}
     * @param o   参数1:代理类对象
     * @param method  参数2:被代理对象的业务方法 {注意:这里是概论的即统一所有的被代理对象的方法都用method表示,具体的是什么方法就需要具体的传入被代理对象来决定}
     * @param arg    参数3:被代理对象的方法的参数
     * @return
     */
    @Override
    public Object invoke(Object o, Method method, Object[] arg) throws Throwable {
        // 切面代码
        beforeSing();
        // 要执行的被代理对象的业务方法
        Object obj = method.invoke(object, arg);
        // 切面代码
        afterSing();
        return null;
    }

    // 测试类
    public static void main(String[] args) {
        // 创建刘德华歌手
        LiuSinger liu = new LiuSinger();
        // 创建代理对象
        SingerDynamicProxy proxy = new SingerDynamicProxy(liu);
        // 绑定歌手跟代理的关系
        // getClassLoader()叫类加载器:把一个类加载到内存里面
        // getInterfaces() 获取类的所有接口方法
        // proxy 传入要绑定的代理对象
        Singer singer = (Singer) Proxy.newProxyInstance(
                liu.getClass().getClassLoader(),
                liu.getClass().getInterfaces(),
                proxy);
        // 调用歌手方法
        singer.singsong();
    }
}

方法二:

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

/**
 * 动态代理
 * Created by Sheldon on 2019/11/5.
 */
public class SingerDynamicProxy implements InvocationHandler {

    // 代理的对象
    private Object object;

    public SingerDynamicProxy(Object object){
        this.object = object;
    }

    // 唱歌之前
    public void beforeSing(){
        System.out.println("动态-布置会场ing");
    }

    // 唱歌之后
    public void afterSing(){
        System.out.println("动态-清理会场ing");
    }

    // 绑定关系(返回绑定好关系的代理实例)
    // getClassLoader()叫类加载器:把一个类加载到内存里面
    // getInterfaces() 获取类的所有接口方法
    // 如下是固定的写法,套路来的,得到代理对象(与传入对象有关)
    public Object newProxyInstance(){
        return Proxy.newProxyInstance(
                object.getClass().getClassLoader(),
                object.getClass().getInterfaces(),
                this);
    }

    /**
     * 代理对象要执行的方法:{即真正需要执行的代理对象的业务方法}
     * @param o   参数1:代理类对象
     * @param method  参数2:被代理对象的业务方法 {注意:这里是概论的即统一所有的被代理对象的方法都用method表示,具体的是什么方法就需要具体的传入被代理对象来决定}
     * @param arg    参数3:被代理对象的方法的参数
     * @return
     */
    @Override
    public Object invoke(Object o, Method method, Object[] arg) throws Throwable {
        // 切面代码
        beforeSing();
        // 要执行的被代理对象的业务方法
        Object obj = method.invoke(object, arg);
        // 切面代码
        afterSing();
        return null;
    }

    // 测试类
    public static void main(String[] args) {
        // 创建刘德华歌手
        LiuSinger liu = new LiuSinger();
        // 创建代理对象
        SingerDynamicProxy proxy = new SingerDynamicProxy(liu);
        // 获取代理对象实例
        Singer proxyInstance = (Singer) proxy.newProxyInstance();
        // 调用歌手方法
        proxyInstance.singsong();
    }
}
动态代理demo测试
上一篇下一篇

猜你喜欢

热点阅读