动态代理:在程序运行时,运用反射机制动态创建而程。
直接上代码,代理模式将实际工作类和客户端解耦,通过中间代理进行辅助功能的添加,如下列代码:
public interface Account {、、
public void query();
public void test();
}
//真正的工作类
public class RealAccount implements Account{
@Override
public void query() {
System.out.println("真正的工作类在进行查询");
}
@Override
public void test() {
System.out.println("真正的工作类在进行测试");
}
}
//静态代理类,提供辅助功能
public class StaticAccountProxy implements Account {
private RealAccount realaccount;
StaticAccountProxy(RealAccount realaccount){
this.realaccount = realaccount;
}
@Override
public void query() {
System.out.println("代理类进行查询辅助功能---------------By proxy");
realaccount.query();
}
@Override
public void test() {
System.out.println("代理类进行测试辅助功能---------------By proxy");
realaccount.test();
}
public static void main(String[] args) {
RealAccount real = new RealAccount();
StaticAccountProxy proxy = new StaticAccountProxy(real);
proxy.query();
proxy.test();
}
}
测试结果如下:
代理类进行查询辅助功能---------------By proxy
真正的工作类在进行查询
代理类进行测试辅助功能---------------By proxy
真正的工作类在进行测试
静态代理的缺陷就是当借口很多的时候,必须预定义很多静态代理类,造成代码重复,因此我们联想到了动态代理:
动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码。动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java 反射机制可以生成任意类型的动态代理类。java.lang.reflect 包中的Proxy类和InvocationHandler 接口提供了生成动态代理类的能力。 原来是利用反射的机制来实现的,今天我们不讨论反射,我们看JDK的动态代理的实现。
JDK动态代理中包含一个类和一个接口: InvocationHandler接口,和我们定义的一个实现类“Proxy“,这是一个万能的代理类,我们就是通过这个代理类来动态代理的。
InvocationHandler接口:
public interface InvocationHandler {
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable;
}
参数说明:
Object proxy:指被代理的对象。
Method method:要调用的方法
Object[] args:方法调用时所需要的参数
可以将InvocationHandler接口的子类想象成一个代理的最终操作类,替换掉ProxySubject。
Proxy类:
Proxy类是专门完成代理的操作类,可以通过此类为一个或多个接口动态地生成实现类,此类提供了如下的操作方法:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
throws IllegalArgumentException
参数说明:
ClassLoader loader:类加载器
Class<?>[] interfaces:得到全部的接口
InvocationHandler h:得到InvocationHandler接口的子类实例
public class DynamicProxy implements InvocationHandler{
//实际对象
private Object realAccaount;
public Object getInstance(Object realAccaount){
this.realAccaount =realAccaount;
return Proxy.newProxyInstance(realAccaount.getClass().getClassLoader(), realAccaount.getClass().getInterfaces(), this);
//通过这个方法返回动态代理,实际是Proxy.newProxyInstance()方法,第一个,第二个参数要是真正代理类的类加载器和实现的接口,第三个参数要是实现了invovationH
//andler的类,因为会调用他的invoke方法
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
System.out.println("动态代理提供的辅助功能------first");
result = method.invoke(realAccaount, args); //注意,这里的第一个参数一定是realObject,即真正的工作类
System.out.println("动态代理提供的辅助功能------end");
return result;
}
public static void main(String[] args) {
DynamicProxy proxy = new DynamicProxy();
Account account = (Account) proxy.getInstance(new RealAccount());
account.query();
account.test();
}
}
测试结果如下:
动态代理提供的辅助功能------first
真正的工作类在进行查询
动态代理提供的辅助功能------end
动态代理提供的辅助功能------first
真正的工作类在进行测试
动态代理提供的辅助功能------end