类对象操作时候在外面加一层代理,加一层壳,比如写日记功能,写在外面不接触具体操作对象,相当于代理对厂家的宣传作用。
下面是JDK动态代理
//makeProxy.java
package daili; import com.sun.org.apache.xpath.internal.SourceTree; import java.lang.reflect.*; import java.util.Arrays; /* 这个类生成代理对象 JDK动态代理 1:Proxy:是所有动态代理的父类,专门用于生成代理类或者生成代理对象 这里的proxy是 java.lang.reflect Class<?>(返回值) getPRoxyClass()方法用于生成对象的Class对象,就是电脑计算机中的class对象,属性就是class object(返回值) newProxyInstance()方法用于生成代理对象的实例 2:InvocationHandler:完成动态代理的整个过程,这是一个接口,自己写一个类实现它 里面有一个invoke方法(返回值是object) */ public class makeProxy { //动态代理 : 目标对象 如何获取代理对象 代理要干什么 //目标对象 private caculate cal ; //获取代理对象需要执行方法,此时需要new makeProxy,所以直接放到构造方法中,此时的参数就是目标对象 public makeProxy(caculate cal){ this.cal = cal; } //获取代理对象的方法 public Object getProxy(){ //代理对象 Object proxy; /* 第一个参数:ClassLoader对象。类加载器对象 第二个参数:interfaces :接口们。提供目标对象的所有接口,用于实现代理对象和目标对象实现的是同一个接口。就是在代理对象.之后可以出现目标对象的方法. 第三个参数:是一个实现InvocationHandler接口的类对象,这里的 */ ClassLoader loader = cal.getClass().getClassLoader(); //类加载器 Class [] interfaces = cal.getClass().getInterfaces(); //下面这个有三个参数 proxy = Proxy.newProxyInstance(loader,interfaces,new MyInvocationHandler()); return proxy; } class MyInvocationHandler implements InvocationHandler{ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Exception { /* 这里的proxy参数和上面的proxy = Proxy.newProxyInstance(loader,interfaces,new MyInvocationHandler());,这句话生成的proxy是一个东西,一般不要动,慎用。 这里的method是一个正在被调用的方法的对象,就是这个参数是一个对象,该对象能执行的方法就是此时正在被执行的方法,比如add方法 args是此时正在被调用方法的参数 */ //先将正事办了,代理代理的那个目标对象的方法,先把这个执行了 System.out.println("日记执行开始:"+method.getName()+" "+ Arrays.asList(args)); Object object = method.invoke(cal,args);//执行caculateImpl里面的+ - * / System.out.println("日记执行结束:结果是-->"+object); return object; } } }
tast.java
package daili; public class test { public static void main(String[] args) { caculate cal = new caculateImpl(); Object obj = new makeProxy(cal).getProxy(); caculate pro = (caculate) obj; System.out.println(pro.add(1, 2)); } /* 问题1:代理对象目标对象能否互相转化? 不行,两个只有实现的接口一样 问题2:代理对象执行代理方法,为什么会执行实现InvacationHandler对象中的invoke方法 System.out.println(pro.getClass().getName()); 此时可以得到该代理对象的类名字是$Proxy0 此时底层的$Proxy0是这样实现的 class $Proxy0 extends Proxy implements caculate{ //这里的构造方法是将自己定义的MyInvocationHandler对象赋值到父类中的h public $Proxy0(InvocationHandler h) { super(h); } //在上面对父类的InvocationHandler h中的h赋值之后,每一次调用代理类的代理方法时候,都会执行下面这样的invoke方法。 @Override public int add(int a, int b) { return super.h.invoke(this,对象方法,对象参数); 执行父类中的invoke方法,也就是那个自己写的invoke方法。 } } */ }
//caculateImpl.java
package daili; public class caculateImpl implements caculate { @Override public int add(int a, int b) { return a+b; } }
//caculate.java
package daili; public interface caculate { public int add(int a,int b); }
代理模式有两种,基于接口的,基于继承的
基于接口的:代理类和普通类只能代理接口里面的方法,目标对象中声明的新方法,代理对象代理不了
基于继承的:代理继承目标对象,这样在目标对象中自己写的方法也可以代理。