设计模式之代理模式

  • 代理模式(Proxy pattern)

    • 抽象角色:定义代理角色和真实角色的公共对外方法
    • 真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用
    • 代理角色:实现抽象,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作
  • 代理对象和目标对象都要实现指定的接口

  • 代理对象要包含目标对象

  • 代理对象对照目标对象进行增强

静态代理(static proxy)

  • 抽象角色
package designmode.proxy.staticproxy;
public interface Star {
    /**
     * 面谈
     */
    void confer();
    /**
     * 签合同
     */
    void signContract();
    /**
     * 订票
     */
    void bookTicket();
    /**
     * 唱歌
     */
    void sing();
    /**
     * 收尾款
     */
    void collectMoney();
}
  • 目标对象
package designmode.proxy.staticproxy;
public class RealStar implements Star{
    @Override
    public void confer() {

    }
    @Override
    public void signContract() {

    }
    @Override
    public void bookTicket() {

    }
    @Override
    public void sing() {
        System.out.println("周杰伦本人唱歌");

    }
    @Override
    public void collectMoney() {

    }
}
  • 代理对象
package designmode.proxy.staticproxy;
public class ProxyStar implements Star{

    private Star star;

    public ProxyStar(Star star) {
        this.star = star;
    }
    @Override
    public void confer() {
        System.out.println("面谈");
    }
    @Override
    public void signContract() {
        System.out.println("签合同");

    }
    @Override
    public void bookTicket() {
        System.out.println("订票");

    }
    @Override
    public void sing() {
        star.sing();

    }
    @Override
    public void collectMoney() {
        System.out.println("收尾款");

    }
}
  • 测试
package designmode.proxy.staticproxy;
public class Client {
    public static void main(String[] args) {
        Star real = new RealStar();
        Star proxy = new ProxyStar(real);
        proxy.confer();
        proxy.signContract();
        proxy.bookTicket();
        proxy.sing();
        proxy.collectMoney();
    }
}

  • 动态代理(jdk代理)

    • 抽象角色

package designmode.proxy.dynamicproxy;
public interface Star {
    /**
     * 面谈
     */
    void confer();
    /**
     * 签合同
     */
    void signContract();
    /**
     * 订票
     */
    void bookTicket();
    /**
     * 唱歌
     */
    void sing();
    /**
     * 收尾款
     */
    void collectMoney();
}
  • 真实角色

package designmode.proxy.dynamicproxy;
public class RealStar implements Star{
    @Override
    public void confer() {
        System.out.println("和经纪人面谈");
    }
    @Override
    public void signContract() {
        System.out.println("和经纪公司签合同");
    }
    @Override
    public void bookTicket() {
        System.out.println("订票");
    }
    @Override
    public void sing() {
        System.out.println("周杰伦本人唱歌");

    }
    @Override
    public void collectMoney() {
        System.out.println("付尾款");
    }
}
  • 处理器类

package designmode.proxy.dynamicproxy;

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

public class StarHandler implements InvocationHandler{

    private Object realStar;


    public StarHandler(ObjectrealStar) {
        this.realStar = realStar;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object obj = null;
        System.out.println("面谈,签合同,预付款,订票");
        if(method.getName().equals("sing")) {
            obj = method.invoke(realStar, args);
        }
        System.out.println("收尾款");
        return obj;
    }

}
  • 测试

package designmode.proxy.dynamicproxy;
import java.lang.reflect.Proxy;
public class Client {
    public static void main(String[] args) {
        Star realStar = new RealStar();
        StarHandler handler = new StarHandler(realStar);
        Star proxy = (Star) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[] {Star.class}, handler);
        proxy.sing();
    }
}

  • CGLIB动态代理

    • 利用ASM开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

  • 目标对象

package designmode.proxy.cglib;
public class TeacherDao {

    public void teach() {
        System.out.println("老师授课中,我是cglib代理,不需要实现接口");
    }
}
  • 代理实现

package designmode.proxy.cglib;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class ProxyFactory implements MethodInterceptor{

    private Object target;

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

    // 返回一个代理对象,是target对象的代理对象
    public Object getProxyInstance() {
        // 创建一个工具类
        Enhancer enhancer = new Enhancer();
        //设置父类
        enhancer.setSuperclass(target.getClass());
        // 设置回调函数
        enhancer.setCallback(this);
        //创建子类对象,即代理对象
        return enhancer.create();
    }

    //重写intercept方法,会调用目标对象的方法
    @Override
    public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
        System.out.println("Cglib代理模式开始");
        Object returnValue = arg1.invoke(target, arg2);
        System.out.println("Cglib代理提交");
        return returnValue;
    }

}
  • 测试

package designmode.proxy.cglib;
public class Client {
    public static void main(String[] args) {
        TeacherDao target = new TeacherDao();
        TeacherDao proxy =(TeacherDao) new ProxyFactory(target).getProxyInstance();
        proxy.teach();
    }
}

注意:cglib支持jdk8以下的版本,8以上的版本报类型转换错误

参考资料:
https://www.jianshu.com/p/46d092bb737d



来自为知笔记(Wiz)


posted on 2021-01-17 12:15  白衣风云  阅读(106)  评论(0编辑  收藏  举报

导航