代理设计模式

一.代理设计模式

1. 设计模式:前人总结的一套解决特定问题的代码.
2. 代理设计模式优点:
  1)保护真实对象
  2)让真实对象职责更明确.
  3)扩展
3. 代理设计模式
  1)真实对象(老总)
  2)代理对象(秘书)
  3)抽象对象(抽象功能),谈小目标

二.静态代理设计模式

1. 由代理对象代理所有真实对象的功能.
  1)自己编写代理类
  2)每个代理的功能需要单独编写
2. 静态代理设计模式的缺点:
  当代理功能比较多时,代理类中方法需要写很多.
3.代码示例
  1)实现功能接口:抽象对象(抽象功能)

public interface Gongneng{
    void zhidingxiaomubiao();
    void chifan();
}

  2)真实对象(老总)

public class Laozong implements Gongneng {
    private String name;
public String getName() { return name; } public void setName(String name) { this.name = name; } public Laozong(String name) { this.name = name; } public Laozong() { }
@Override
public void zhidingxiaomubiao(){ System.out.println("制定小目标"); } @Override public void chifan() { System.out.println("老总吃饭"); } }

  3)代理对象(秘书)

public class MiShu implements Gongneng{
    private Laozong laozong = new Laozong("云云");

    @Override
    public void zhidingxiaomubiao() {
        System.out.println("约定时间");
        laozong.zhidingxiaomubiao();
        System.out.println("把访客信息备注");
    }

    @Override
    public void chifan() {
        System.out.println("约定时间");
        laozong.chifan();
        System.out.println("把访客信息备注");
    }
}

  4)测试

public class Women {
    public static void main(String[] args) {
        MiShu mishu = new MiShu();
        mishu.zhidingxiaomubiao();
    }
}

三.动态代理

1. 为了解决静态代理频繁编写代理功能缺点.
2. 分类:
  1)JDK 提供的
  2)cglib 动态代理

(一)JDK 动态代理

1. 和 cglib 动态代理对比
  1)优点:jdk 自带,不需要额外导入 jar
  2)缺点:
    真实对象必须实现接口
    利用反射机制.效率不高.
2. 使用 JDK 动态代理时可能出现下面异常
  出现原因:希望把接口对象转换为具体真实对象


3.代码示例
  1)实现功能接口:抽象对象(抽象功能)

public interface Gongneng {
    void chifan();
    void mubiao();
}

2)真实对象(老总)

public class Laozong implements Gongneng{
    
    @Override
    public void chifan() {
        System.out.println("吃饭");
    }

    @Override
    public void mubiao() {
        System.out.println("目标");
    }
    
}

3)代理对象(秘书)

public class Mishu implements InvocationHandler {
    private Laozong laozong=new Laozong() ;
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("预约时间");
        Object result = method.invoke(laozong, args);
        System.out.println("记录访客信息");
        return result;
    }
}

4)测试

public class Women {
    public static void main(String[] args) {
        Mishu mishu = new Mishu();
        //第一个参数:反射时使用的类加载器
        //第二个参数:Proxy需要实现什么接口
        //第三个参数:通过接口对象调用方法时,需要调用哪个类的invoke方法
        Gongneng gongneng = (Gongneng) Proxy.newProxyInstance(Women.class.getClassLoader(), new Class[]{Gongneng.class}, mishu);
        gongneng.chifan();
    }
}

(二)cglib 动态代理

1. cglib 优点:
  1)基于字节码,生成真实对象的子类.
    运行效率高于 JDK 动态代理.
  2)不需要实现接口
2. cglib 缺点:
  非 JDK 功能,需要额外导入 jar
3. 使用 spring aop 时,只要出现 Proxy 和真实对象转换异常,应在applicationContext.xml中加下面一句话:
  1)设置为 true 使用 cglib
  2)设置为 false 使用 jdk(默认值)

 

<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>

4.代码示例
  1)真实对象(老总)

public class Laozong {
    
    public void chifan() {
        System.out.println("吃饭");
    }

    public void mubiao() {
        System.out.println("目标");
    }

}

  2)代理对象(秘书)

public class Mishu implements MethodInterceptor{

    @Override
    public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
        System.out.println("预约时间");
        //invoke()调用子类重写的方法
        //arg1.invoke(arg0, arg2);
        //arg3.invokeSuper(arg0, arg2);
        Object result = arg3.invokeSuper(arg0, arg2);
        System.out.println("备注");
        return result;
    }
}

  3)测试

public class Women {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(Laozong.class);
        enhancer.setCallback(new Mishu());
        
        Laozong laozong = (Laozong) enhancer.create();
        laozong.chifan();  
    }
}

 

posted @ 2020-04-11 14:04  溯鸣  阅读(288)  评论(0编辑  收藏  举报