出处:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html
动态代理
概念
与静态代理类对照的是动态代理类,动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码。
动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java 反射机制可以生成任意类型的动态代理类。
java.lang.reflect 包中的Proxy类和InvocationHandler 接口提供了生成动态代理类的能力。
例子(用例子讲比较容易接受)
先给一个例子:
接口:BookFacade.java
委托类:BookFacadeImpl.java
代理类:BookFacadeProxy.java
主程序类:TestProxy.java
本例的:
委托类实现接口BookFacade.java
代理类实现InvocationHandler 接口并等待接受委托类对象
主程序类:新建委托类对象,并传递给代理类,代理类返回代理类对象,实现动态代理。
具体代码如下:
BookFacade.java
package net.battier.dao;
public interface BookFacade {
public void addBook();
}
BookFacadeImpl.java
package net.battier.dao.impl;
import net.battier.dao.BookFacade;
public class BookFacadeImpl implements BookFacade {
public void addBook() {
System.out.println("增加图书方法。。。");
}
}
BookFacadeProxy.java
package net.battier.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* JDK动态代理代理类
*
* @author student
*
*/
public class BookFacadeProxy implements InvocationHandler {
private Object target;
/**
* 绑定委托对象并返回一个代理类
* @param target
* @return
*/
public Object bind(Object target) {
this.target = target;
//取得代理对象
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this); //要绑定接口(这是一个缺陷,cglib弥补了这一缺陷)
}
@Override
/**
* 调用方法
*/
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result=null;
System.out.println("事物开始");
//执行方法
result=method.invoke(target, args);
System.out.println("事物结束");
return result;
}
}
TestProxy.java
package net.battier.test;
import net.battier.dao.BookFacade;
import net.battier.dao.impl.BookFacadeImpl;
import net.battier.proxy.BookFacadeProxy;
public class TestProxy {
public static void main(String[] args) {
BookFacadeProxy proxy = new BookFacadeProxy();
BookFacade bookProxy = (BookFacade) proxy.bind(new BookFacadeImpl());
bookProxy.addBook();
}
}
JDK动态代理
JDK动态代理中包含一个类和一个接口:
InvocationHandler//接口:
public interface InvocationHandler {
public Object invoke( Object proxy ,Method method ,Object[] args ) throws Throwable;
}
/*
参数说明:
Object proxy:指被代理的对象。
Method method:要调用的方法
Object[] args:方法调用时所需要的参数
*/
Proxy类:
Proxy类是专门完成代理的操作类,可以通过此类为一个或多个接口动态地生成实现类,此类提供了如下的操作方法:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
/*
newProxyInstance(
ClassLoader loader,//类加载器
Class<?>[] interfaces, //得到全部的接口
InvocationHandler h //得到InvocationHandler接口的子类实例
)
*/
Ps:类加载器 在Proxy类中的newProxyInstance()方法中需要一个ClassLoader类的实例,ClassLoader实际上对应的是类加载器,在Java中主要有一下三种类加载器; Booststrap ClassLoader:此加载器采用C++编写,一般开发中是看不到的; Extendsion ClassLoader:用来进行扩展类的加载,一般对应的是jre\lib\ext目录中的类; AppClassLoader:(默认)加载classpath指定的类,是最常使用的是一种加载器。
接口的动态代理类的实例:(自己貌似有些混乱。。。)
/**** 方式一 ****/
//创建InvocationHandler对象
InvocationHandler handler = new MyInvocationHandler(...);
//创建动态代理类
Class proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(), new Class[] { Foo.class });
//创建动态代理类的实例
Foo foo = (Foo) proxyClass.getConstructor(new Class[] { InvocationHandler.class }).
newInstance(new Object[] { handler });
/**** 方式二 ****/
//创建InvocationHandler对象
InvocationHandler handler = new MyInvocationHandler(...);
//直接创建动态代理类的实例
Foo foo = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),new Class[] { Foo.class }, handler);
自己的实例(虽并不规范,但是也有点特别的地方)
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
/**
* 第二题:写一个ArrayList类的代理,实现和ArrayList中完全相同的功能.。
* author:neo37927
*/
public class Test{
public static void main(String[] args) throws Exception {
//建立并传入ArrayList委托对象
List realClass = new ArrayList();
//接受代理类
Object newList = newClass(realClass);
//设定要调用的方法
((List) newList).add("itheima");
((List) newList).get(0);
((List) newList).size();
System.out.println(newList);
}
//动态代理,接受委托类(函数实现,本人以前是学C的,so...)
public static Object newClass(final Object realClass){
//取得代理类对象,并返回
return Proxy.newProxyInstance(
realClass.getClass().getClassLoader(),//第一个参数——加载类
realClass.getClass().getInterfaces(),//第二个参数——取得接口
new InvocationHandler() {//第三个参数——调用方法
public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
//执行方法
Object result = method.invoke(realClass, args);
return result;
}
}
);
}
}
网友龙四的代码
出处:http://bbs.csdn.net/topics/390301793?page=1
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
public class ListProxy {
public static void main(String[] args) throws Exception {
List<String> list = newList(String.class);
list.add("abc");
System.out.println(list);
}
@SuppressWarnings("unchecked")
public static <T> List<T> newList(Class<T> elementType) {
return (List<T>)Proxy.newProxyInstance(List.class.getClassLoader(), new Class[]{List.class}, new InvocationHandler() {
private List<T> realList = new ArrayList<T>();
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
long start = System.nanoTime();
Object ret = method.invoke(realList, args);
long end = System.nanoTime();
System.out.println("调用" + method.getName() + "耗时:" + (end - start) + "纳秒");
return ret;
}
});
}
}