代理设计模式
一.代理设计模式
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(); } }