目录
代理模式(Proxy Pattern)
代理模式是一种软件设计模式,为某个实现类(也称目标类或委托类)对象提供一个代理类,代理类通过控制该对象的访问可以为该对象中的方法增加额外的功能。
静态代理
静态代理由一个接口、实现类(也称目标类或委托类)、代理类三部分组成,实现类和代理类均须实现接口中定义的抽象方法,不同之处在于,实现类负责实现主要的业务方法,代理类负责对实现类中的业务方法作“加强”处理:在调用的业务方法前后增加额外的处理。调用业务时,通过代理类对象调用代理类中接口实现方法,进而间接调用实现类中业务方法。
注意:
1、所谓静态是指程序运行前代理类对应字节码文件已经存在,且代理类和委托类的关系已经确定了。
2、代理类和委托类有共同的父类或父接口。
3、实现类和代理类实现同一个接口,所以实现类和代理类拥有相同的方法。定义一个接口:
public interface ICalculatorService { int add(int a,int b); int sub(int a,int b); int mul(int a,int b); int div(int a,int b); }
接口实现类代码如下:
public class CalculatorService implements ICalculatorService { @Override public int add(int a, int b) { int result = a+b; return result; } @Override public int sub(int a, int b) { int result = a-b; return result; } @Override public int mul(int a, int b) { int result = a*b; return result; } @Override public int div(int a, int b) { int result = a/b; return result; } }
创建静态代理类,该类实现ICalculatorService接口
public class Proxy implements ICalculatorService{ private CalculatorService target; public Proxy(CalculatorService target) { this.target = target; } @Override public int add(int a, int b) { System.out.println(this.getClass().getName()+":The add method begins."); System.out.println(this.getClass().getName()+":Parameters of the add method: ["+a+","+b+"]"); int result = target.add(a, b); System.out.println(this.getClass().getName()+":Result of the add method:"+result); System.out.println(this.getClass().getName()+":The add method ends."); return result; } @Override public int sub(int a, int b) { System.out.println(this.getClass().getName()+":The sub method begins."); System.out.println(this.getClass().getName()+":Parameters of the sub method: ["+a+","+b+"]"); int result = target.sub(a, b); System.out.println(this.getClass().getName()+":Result of the sub method:"+result); System.out.println(this.getClass().getName()+":The sub method ends."); return result; } @Override public int mul(int a, int b) { System.out.println(this.getClass().getName()+":The mul method begins."); System.out.println(this.getClass().getName()+":Parameters of the mul method: ["+a+","+b+"]"); int result = target.mul(a, b); System.out.println(this.getClass().getName()+":Result of the mul method:"+result); System.out.println(this.getClass().getName()+":The mul method ends."); return result; } @Override public int div(int a, int b) { System.out.println(this.getClass().getName()+":The div method begins."); System.out.println(this.getClass().getName()+":Parameters of the div method: ["+a+","+b+"]"); int result = target.div(a, b); System.out.println(this.getClass().getName()+":Result of the div method:"+result); System.out.println(this.getClass().getName()+":The div method ends."); return result; } }
import com.jd.calculator.CalculatorService; import com.jd.calculator.ICalculatorService; import com.jd.calculator.Proxy; public class Test { public static void main(String[] args) { ICalculatorService proxy = new Proxy(new CalculatorService()); int result = proxy.add(1, 2); System.out.println("-->"+result); result = proxy.div(1, 1); System.out.println("-->"+result); } }
CalculatorService类中代码可以通过代理模式进行优化,Java中代理模式分为静态代理和动态代理
动态代理-----JDK动态代理
动态代理-是在程序运行期间JVM根据需要通过反射等机制动态地创建代理类及其代理对象。
JDK动态代理-程序执行时使用java.lang.reflect包中Proxy类与InvocationHandler接口动态地生成一个实现代理接口的匿名代理类及其对象,无论调用代理对象哪个方法,最终都会执行invoke方法。
注意:
1、代理类是在程序运行期间创建,可以在classpath目录(在Eclipse中,Java工程中的bin目录;Web工程中的build目录)中看到该文件,
2、代理类和委托类的关系是在程序运行时确定的。定义一个接口
public interface ICalculatorService { int add(int a,int b); int sub(int a,int b); int mul(int a,int b); int div(int a,int b); }
接口实现类如下:
public class CalculatorService implements ICalculatorService { @Override public int add(int a, int b) { int result = a+b; return result; } @Override public int sub(int a, int b) { int result = a-b; return result; } @Override public int mul(int a, int b) { int result = a*b; return result; } @Override public int div(int a, int b) { int result = a/b; return result; } }
动态代理:
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class Add { public static void main(String[] args) { //最终目标:调用CalculatorService类中的add方法 ICalculatorService calculatorService=new CalculatorService(); System.out.println("calculatorService------->"+calculatorService); System.out.println("----------"+calculatorService.getClass().getName()); //匿名内部类 InvocationHandler handler =new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("proxy.getClass().getName()----->"+proxy.getClass().getName()); String name=method.getName(); System.out.println(calculatorService.getClass().getName()+":The "+name+" method begins."); System.out.println(calculatorService.getClass().getName()+":Parameters of the "+name+" method: ["+args[0]+","+args[1]+"]"); Object result = method.invoke(calculatorService, args); //反射中方法的调用,调用目标方法,也就是调用CalculatorService中的 add方法 System.out.println(calculatorService.getClass().getName()+":Result of the "+name+" method:"+result); System.out.println(calculatorService.getClass().getName()+":The "+name+" method ends."); return result; } }; //用JDK的方式创建动态代理对象,这个对象的特点:和CalculatorService类实现的接口相同 ClassLoader classLoader =calculatorService.getClass().getClassLoader(); // Proxy.newProxyInstance创建此对象的类是不存在的 ,只有执行的时候才能确定对象 ICalculatorService cService= (ICalculatorService) Proxy.newProxyInstance(classLoader, new Class[] {ICalculatorService.class}, handler); System.out.println("cService--------->"+cService.getClass().getName()); int result=cService.add(1, 2); //cService存放的是由Proxy创建的实现的ICalculatorService的一个匿名内部类 //cService.add(1, 2);方法调用的是由proxy类创建的匿名内部类对象中的add方法 System.out.println(result); } }
将动态代理类进行封装:
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class ProxyFactory { static ICalculatorService target;//目标对象 // 匿名内部类 static InvocationHandler handler = new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("proxy.getClass().getName()----->" + proxy.getClass().getName()); String name = method.getName(); System.out.println(target.getClass().getName() + ":The " + name + " method begins."); System.out.println(target.getClass().getName() + ":Parameters of the " + name + " method: [" + args[0] + "," + args[1] + "]"); Object result = method.invoke(target, args); // 反射中方法的调用,调用目标方法,也就是调用CalculatorService中的 add方法 System.out.println(target.getClass().getName() + ":Result of the " + name + " method:" + result); System.out.println(target.getClass().getName() + ":The " + name + " method ends."); return result; } }; public static Object getProxy(ICalculatorService target) { ProxyFactory.target=target; return Proxy.newProxyInstance(target.getClass().getClassLoader(), CalculatorService.class.getInterfaces(), handler); } }
测试类:
public class Test { public static void main(String[] args) { ICalculatorService cService= (ICalculatorService) ProxyFactory.getProxy(new CalculatorService() ); System.out.println("cService--------->"+cService.getClass().getName()); int result=cService.add(1, 2); //cService存放的是由Proxy创建的实现的ICalculatorService的一个匿名内部类 System.out.println(result); } }
注意:
1.Proxy.newProxyInstance的这个对象所实现的接口和CalculatorService类所实现的接口相同,所以interface是CalculatorService.class.getInterfaces()
2.handler 告诉对象做什么,只有在执行的时候对象才能确定,所以是动态的
3.cService.add(1, 2)方法的执行过程:先执行代理对象里的方法,然后到达目标对象中的方法,最后在回到代理对象中的方法,返回结果
输出JDK动态代理产生的class文件
生成使用JDK创建动态代理对象的class文件。注意:该行代码必须放在代理对象产生之前
public class Test { public static void main(String[] args) { // 生成使用JDK创建动态代理对象的class文件。注意:该行代码必须放在代理对象产生之前 System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true"); ICalculatorService cService = (ICalculatorService) ProxyFactory.getProxy(new CalculatorService()); System.out.println("cService--------->" + cService.getClass().getName()); int result = cService.add(1, 2); // cService存放的是由Proxy创建的实现的ICalculatorService的一个匿名内部类 // cService.add(1, 2);调用的是由proxy类创建的匿名内部类对象中的add方法 System.out.println(result); } }
用反编译器将生成的.class文件还原成.java文件:
package com.sun.proxy; import fuxiTest.java.jdk.calculator.ICalculatorService; import java.lang.reflect.*; public final class $Proxy0 extends Proxy implements ICalculatorService { public $Proxy0(InvocationHandler invocationhandler) { super(invocationhandler); } public final boolean equals(Object obj) { try { return ((Boolean)super.h.invoke(this, m1, new Object[] { obj })).booleanValue(); } catch(Error _ex) { } catch(Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } public final String toString() { try { return (String)super.h.invoke(this, m2, null); } catch(Error _ex) { } catch(Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } public final int mul(int i, int j) { try { return ((Integer)super.h.invoke(this, m5, new Object[] { Integer.valueOf(i), Integer.valueOf(j) })).intValue(); } catch(Error _ex) { } catch(Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } public final int add(int i, int j) { try { return ((Integer)super.h.invoke(this, m3, new Object[] { Integer.valueOf(i), Integer.valueOf(j) })).intValue(); } catch(Error _ex) { } catch(Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } public final int sub(int i, int j) { try { return ((Integer)super.h.invoke(this, m4, new Object[] { Integer.valueOf(i), Integer.valueOf(j) })).intValue(); } catch(Error _ex) { } catch(Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } public final int div(int i, int j) { try { return ((Integer)super.h.invoke(this, m6, new Object[] { Integer.valueOf(i), Integer.valueOf(j) })).intValue(); } catch(Error _ex) { } catch(Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } public final int hashCode() { try { return ((Integer)super.h.invoke(this, m0, null)).intValue(); } catch(Error _ex) { } catch(Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } private static Method m1; private static Method m2; private static Method m5; private static Method m3; private static Method m4; private static Method m6; private static Method m0; static { try { m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") }); m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]); m5 = Class.forName("fuxiTest.java.jdk.calculator.ICalculatorService").getMethod("mul", new Class[] { Integer.TYPE, Integer.TYPE }); m3 = Class.forName("fuxiTest.java.jdk.calculator.ICalculatorService").getMethod("add", new Class[] { Integer.TYPE, Integer.TYPE }); m4 = Class.forName("fuxiTest.java.jdk.calculator.ICalculatorService").getMethod("sub", new Class[] { Integer.TYPE, Integer.TYPE }); m6 = Class.forName("fuxiTest.java.jdk.calculator.ICalculatorService").getMethod("div", new Class[] { Integer.TYPE, Integer.TYPE }); m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]); } catch(NoSuchMethodException nosuchmethodexception) { throw new NoSuchMethodError(nosuchmethodexception.getMessage()); } catch(ClassNotFoundException classnotfoundexception) { throw new NoClassDefFoundError(classnotfoundexception.getMessage()); } } }
return ((Integer)super.h.invoke(this, m3, new Object[] {
Integer.valueOf(i), Integer.valueOf(j)
})).intValue();
执行h就是传入的handler匿名内部类对象的重写的invoke方法