1.代理模式的基本介绍:
1.代理模式:为一个对象提供一个替身来控制对这个对象(被代理的对象)的访问。也就是通过代理对象来访问目标对象(间接访问目标对象),这样的好处就是可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能。
2.被代理的对象可以是远程对象、创建开销大的对象或者需要安全控制的对象。
3.形式:静态代理、动态代理(JDK代理、接口代理)和Cglib代理(可在内存中动态创建对象,而不需要实现接口,它是属于动态代理的范畴)。
4.代理模式的示意图
Client调用TargetObject是通过ProxyObject来实现的,这就是代理
=========================================================================================================================================
2.代理模式的分类
1.静态代理
1.基本介绍:
静态代理在使用时,需要定义接口或者父类,被代理对象(目标对象)与代理对象一起实现相同的接口或者继承相同的父类。
2.应用实例
1.具体要求:
1.定义一个接口:ITeacherDao
2.目标对象TeacherDao实现ITeacherDao接口
3.使用静态代理方式,那么代理对象TeacherProxy也需要实现ITeacherDao接口
4.调用的时候通过调用代理对象的方法来调用目标对象
5.代理对象与目标对象要实现相同的接口,然后通过调用相同的方法来调用目标对象的方法
2.类图:
3.代码:
1.ITeacherDao接口 2.目标对象代码 3.代理对象代码
4.客户端调用
4.代理对象的优缺点
=========================================================================================================================================
2.动态代理
1.基本介绍
2.JDK中生成动态代理的API
3.动态代理应用实例
1.类图:
getProxyInstance():
1.根据传入的目标对象(TeacherDao)
2.利用反射机制,返回一个代理对象
3.然后通过代理对象,调用目标对象的方法
2.代码:
package com.atguigu.proxy.dynamic //接口 public interface ITeacherDao{ void teach(); //授课的方法 }
package com.atguigu.proxy.dynamic //目标对象 public class TeacherDao implements ITeacherDao{ public void teache(){ System.out.print("老师授课。。。。"); } }
package com.atguigu.proxy.dynamic; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class ProxyFactory { //维护一个目标对象,Object private Object target; //初始化target public ProxyFactory(Object target){ this.target = target; } //给目标对象生成一个代理对象 public Object getProxyInstance(){ //说明: /* public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)*/ /* * 1.ClassLoader loader:指定当前目标对象使用的类加载器,获取类加载器的方法固定 * 2.Class<?>[] interfaces: 目标对象实现的接口类型,使用泛型确定类型 * 3.InvocationHandler h: 事件处理,执行目标对象的方法时,会触发事件处理方法,会 * 把当前执行的目标对象方法作为参数传入 */ return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.print("JDK代理开始。。。"); //反射机制调用目标对象的方法 Object returnVal = method.invoke(target, args); return returnVal; } }); } }
package com.atguigu.proxy.dynamic; public class Client { public static void main(String[] args) { //创建目标对象 ITeacherDao target = new TeacherDao(); //给目标对象创建代理对象,可以转成ITeacherDao ITeacherDao proxyInstance =(ITeacherDao)new ProxyFactory(target).getProxyInstance(); //proxyInstance=class com.sun.proxy.$Proxy0:内存中动态生成了代理对象 System.out.println("proxyInstance" + proxyInstance); //通过代理对象,调用目标对象的方法 proxyInstance.teach(); } }
=========================================================================================================================================
3.Cglib代理
1.基本介绍
2.实现步骤
3.类图
4.代码
1.TeacherDao.java
package com.atguigu.proxy.cglib; public class TeacherDao { public void teach(){ System.out.println("老师授课中。。。我是cglib代理,不需要实现接口"); } }
2.ProxyFactory.java
package com.atguigu.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() { // 1. 创建一个工具类 Enhancer enhancer = new Enhancer(); // 2. 设置父类 enhancer.setSuperclass(target.getClass()); // 3. 设置回调函数 enhancer.setCallback(this); // 4. 创建子类对象,即代理对象 return enhancer.create(); } // 重写 intercept 方法,调用目标对象的方法时会触发该方法的调用,从而调用目标对象的方法 @Override public Object intercept(Object arg0, Method method, Object[] args, MethodProxy arg3) throws Throwable { // TODO Auto-generated method stub System.out.println("Cglib代理模式 ~~ 开始"); Object returnVal = method.invoke(target, args); System.out.println("Cglib代理模式 ~~ 提交"); return returnVal; } }
3.Client.java
package com.atguigu.proxy.cglib; public class Client { public static void main(String[] args) { // TODO Auto-generated method stub // 创建目标对象 TeacherDao target = new TeacherDao(); // 获取到代理对象,并且将目标对象传递给代理对象 TeacherDao proxyInstance = (TeacherDao) new ProxyFactory(target).getProxyInstance(); // 执行代理对象的方法,触发intecept 方法,从而实现 对目标对象的调用 proxyInstance.teach(); } }
=========================================================================================================================================
4.代理模式的变体
//目标对象