代理模式
1.进阶篇
1.1动态代理
动态代理即动态的创建代理,并动态的处理对所代理方法的调用。在动态代理上所做的所有调用都会被重定向到单一的调用处理器上,它的工作是揭示调用的类型并确定相应的对策。
下面是动态代理的实例:
public interface Interface {
void doSometing();
void sometingElse(String arg);
}
public class DynamicProxyHandler implements InvocationHandler{
private Object proxied;
public DynamicProxyHandler(Object proxied){
this.proxied=proxied;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
System.out.println("**** proxy"+proxy.getClass()+",method:"+method+",args:"+args);
if(args!=null){
for(Object arg:args)
System.out.println(arg);
}
return method.invoke(proxied, args);
}
public static void main(String[] args) {
RealObject ro=new RealObject();
ro.doSometing();
Interface proxy=(Interface)Proxy.newProxyInstance(
Interface.class.getClassLoader(),
new Class[]{Interface.class},
new DynamicProxyHandler(ro) );
proxy.doSometing();
proxy.sometingElse("nihao");
}
}
// 方法 1: 该方法用于获取指定代理对象所关联的调用处理器
public static InvocationHandler getInvocationHandler(Object proxy)
// 方法 2:该方法用于获取关联于指定类装载器和一组接口的动态代理类的类对象
public static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces)
// 方法 3:该方法用于判断指定类对象是否是一个动态代理类
public static boolean isProxyClass(Class<?> cl)
// 方法 4:该方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例 public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h)
java.lang.reflect.InvocationHandler:调用处理器接口,自定义invokle方法,用于实现对于真正委托类的代理访问
/** 该方法负责集中处理动态代理类上的所有方法调用。 第一个参数既是代理类实例, 第二个参数是被调用的方法对象 第三个方法是调用参数。 调用处理器根据这三个参数进行预处理或分派到委托类实例上发射执行 */
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
3,java.lang.ClassLoader:类装载器类,将类的字节码装载到 Java 虚拟机(JVM)中并为其定义类对象,然后该类才能被使用。Proxy类与普通类的唯一区别就是其字节码是由 JVM 在运行时动态生成的而非预存在于任何一个 .class 文件中。
每次生成动态代理类对象时都需要指定一个类装载器对象:newProxyInstance()方法第一个参数
动态代理机制
java动态代理创建对象的过程为如下步骤:
1,通过实现 InvocationHandler 接口创建自己的调用处理器;
// InvocationHandlerImpl 实现了 InvocationHandler 接口,并能实现方法调用从代理类到委托类的分派转发
// 其内部通常包含指向委托类实例的引用,用于真正执行分派转发过来的方法调用 InvocationHandler handler = new InvocationHandlerImpl(..);
2,通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类;
// 通过 Proxy 为包括 Interface 接口在内的一组接口动态创建代理类的类对象
Class clazz = Proxy.getProxyClass(classLoader, new Class[] { Interface.class, ... });
3,通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;
// 通过反射从生成的类对象获得构造函数对象
Constructor constructor=clazz.getConstructor(new Class[] { InvocationHandler.class
});
4,通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。
// 通过构造函数对象创建动态代理类实例
Interface Proxy = (Interface)constructor.newInstance(new Object[] { handler });
为了简化对象创建过程,Proxy类中的newProxyInstance方法封装了2~4,只需两步即可完成代理对象的创建。
// InvocationHandlerImpl 实现了 InvocationHandler 接口,并能实现方法调用从代理类到委托类的分派转发
InvocationHandler handler = new InvocationHandlerImpl(..);
// 通过 Proxy 直接创建动态代理类实例
Interface proxy = (Interface)Proxy.newProxyInstance( classLoader, new Class[] { Interface.class }, handler );
通过动态代理,我们可以实现事务,其中,代理在被代理的调用执行成功时(不抛出任何异常)执行提交,而在其执行失败的时候进行回滚。