1.代理模式readMe:
代理设计模式: 是java中常用的设计模式! 特点: 01.委托类和代理类有相同的接口或者共同的父类! 02.代理类为委托类负责处理消息,并将消息转发给委托类! 03.委托类和代理类对象通常存在关联关系! 一个代理类对象与一个委托类对象关联! 04.代理类本身并不是真正的实现者!而是通过调用委托类的方法, 来实现功能! 按照代理类创建的时机,代理类分为两种: 01.静态代理:由我们程序猿或者特定的工具自动生成了源代码, 在程序运行之前,.class文件已经存在了! (serviceImpl 调用了 dao层的方法! 真正的实现是Dao) 02.动态代理:在程序运行期间,通过反射的方式动态的创建出来! 按照我们的使用方式: 是由共同的接口还是公共的父类? 01.jdk动态代理 (接口) 必须知道一个类和一个接口 001.InvocationHandler接口只有一个方法 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable; proxy:代理类对象 method:被代理的方法 args:被代理的方法的参数列表 002.Proxy 类: public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h)throws IllegalArgumentException loader:类加载器 interfaces:代理类实现的所有接口 h:InvocationHandler接口的一个实例 this当前对象 因为我们想使用jdk动态代理 必须是 代理类 实现 InvocationHandler! 它让我们传递父接口 我们传递 自身! 02.cglib动态代理(接口+父类) 必须知道一个类和一个接口 001.MethodInterceptor接口 public Object intercept(Object obj, Method method,Object[] args,MethodProxy proxy) throws Throwable; intercept是所有拦截器执行的方法,类似于jdk动态代理中的invoke 002. Enhancer类 设置委托类和代理类的公共接口或者公共的父类 public void setSuperclass(Class superclass) { if (superclass != null && superclass.isInterface()) { setInterfaces(new Class[]{ superclass }); } else if (superclass != null && superclass.equals(Object.class)) { // affects choice of ClassLoader this.superclass = null; } else { this.superclass = superclass; } } 代理类执行完毕 通知委托类 public void setCallback(final Callback callback) { setCallbacks(new Callback[]{ callback }); } 在Enhancer类的父类AbstractClassGenerator中有一个方法 创建我们需要的代理类 protected Object create(Object key)
2.静态代理:
01.接口代码:
package cn.pb.dao; /** * 动物类 父接口 */ public interface Animal { //主业务 void eat(); void sleep(); }
02.实现类代码:
package cn.pb.dao.impl; /** * 狗狗类 实现了Animal接口 */ import cn.pb.dao.Animal; public class Dog implements Animal { public void eat() { System.out.println("狗狗在啃骨头!"); } public void sleep() { System.out.println("狗狗在午休!"); } }
03.静态代理类:
package cn.pb.staticproxy; import cn.pb.dao.Animal; import cn.pb.dao.impl.Dog; /** * 狗狗的静态代理类 */ public class AnimalStaticProxy implements Animal { private Dog dog; public void sleep() { System.out.println("主人在召唤"); //系统级业务 dog.sleep(); System.out.println("主人离开"); //系统级业务 } public void eat() { System.out.println("主人在召唤"); //系统级业务 dog.eat(); System.out.println("主人离开"); //系统级业务 } public Dog getDog() { return dog; } public void setDog(Dog dog) { this.dog = dog; } /** * 我们发现的问题 * 01:代码冗余 * 02:把冗余的代码提取成公共的方法 * 03:有可能小猫咪也有这些方法 * 04:提取成一个工具类中的方法 * 05:现在有一个小猫咪 也需要执行 sleep和eat 以及系统级业务方法 * 06:我们又得创建一个小猫咪对应的代理类 * 07:动物有很多 ,难道需要我们创建N个代理类吗??肯定! */ }
04.测试类代码:
/** * 静态代理的测试方法 */ @Test public void testStaticProxy(){ AnimalStaticProxy proxy = new AnimalStaticProxy(); Dog dog=new Dog(); proxy.setDog(dog); proxy.eat(); System.out.println("*************"); proxy.sleep(); }
3.JDK动态代理:
01.接口代码:
package cn.pb.dao; /** * 动物类 父接口 */ public interface Animal { //主业务 void eat(); void sleep(); }
02.实现类代码:
package cn.pb.dao.impl; /** * 狗狗类 实现了Animal接口 */ import cn.pb.dao.Animal; public class Dog implements Animal { public void eat() { System.out.println("狗狗在啃骨头!"); } public void sleep() { System.out.println("狗狗在午休!"); } }
03.动态代理类代码:
package cn.pb.jdkdynamicproxy; /** * JDK的动态代理类 */ import cn.pb.dao.Animal; import cn.pb.dao.impl.Dog; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class AnimalJdkDynamicProxy implements InvocationHandler { /** * 01.我们不确定委托类是谁?委托类的类型 是Object * 和委托类建立关联关系 */ private Object target; /** * 02.给我一个委托类,我返回一个代理类对象 */ public Object createProxy(Object target){ //根据传递的参数 进行对象的关联 this.target=target; return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); } /** * * @param proxy :代理对象 * @param method :方法名 * @param args : 参数列表 * @return */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("主人在召唤"); //系统级业务 开始事务 Object result= method.invoke(target,args); // 主业务 System.out.println("主人离开"); //系统级业务 日志处理 关闭事务 return result; } //创建测试方法 public static void main(String[] args) { AnimalJdkDynamicProxy proxy=new AnimalJdkDynamicProxy(); Animal dog= (Animal) proxy.createProxy(new Dog()); dog.eat(); System.out.println("**************************"); dog.sleep(); } }
04.测试代码:
@Test public void testJdkDynamicProxy(){ AnimalJdkDynamicProxy proxy=new AnimalJdkDynamicProxy(); Animal dog= (Animal) proxy.createProxy(new Dog()); dog.eat(); System.out.println("**************************"); dog.sleep(); }
4.cglib动态代理:
01.接口代码:
package cn.pb.dao; /** * 动物类 父接口 */ public interface Animal { //主业务 void eat(); void sleep(); }
02.实现类代码:
package cn.pb.dao.impl; /** * 狗狗类 实现了Animal接口 */ import cn.pb.dao.Animal; public class Dog implements Animal { public void eat() { System.out.println("狗狗在啃骨头!"); } public void sleep() { System.out.println("狗狗在午休!"); } }
03.动态代理类代码:
package cn.pb.cglibdynamicproxy; /** * Cglib动态代理 */ import cn.pb.dao.Animal; import cn.pb.dao.impl.Dog; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; public class AnimalCglibDynamicProxy implements MethodInterceptor { /** * 在enhancer中有一个setCallBack(this) * 这样就实现了代理类和委托类的关联 */ private Enhancer enhancer=new Enhancer(); /** * 创建代理类对象 */ public Object createProxy(Class clazz){ //设置公共的接口或者公共的类 enhancer.setSuperclass(clazz); //建立关联关系 enhancer.setCallback(this); return enhancer.create(); } /** * 类似于我们jdk中的invoke */ public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("主人在召唤"); //系统级业务 开始事务 Object result= proxy.invokeSuper(obj,args); // 主业务 System.out.println("主人离开"); //系统级业务 日志处理 关闭事务 return result; } //创建测试方法 public static void main(String[] args) { AnimalCglibDynamicProxy proxy=new AnimalCglibDynamicProxy(); //这里的参数可以传三种形式01:new Dog().getClass() // 02:Class.forName("cn.pb.dao.impl.Dog") 03.Dog.class Animal dog= (Animal) proxy.createProxy(new Dog().getClass()); dog.eat(); System.out.println("**************************"); dog.sleep(); } }
04.测试代码:
@Test public void testCglibDynamicProxy(){ AnimalJdkDynamicProxy proxy=new AnimalJdkDynamicProxy(); Animal dog= (Animal) proxy.createProxy(new Dog()); dog.eat(); System.out.println("**************************"); dog.sleep(); }