接上篇JAVA设计模式之【代理模式】二(静态代理)http://blog.csdn.net/emma_joans/article/details/78564585
动态代理
上述代理方式为静态代理,下面讲述两种动态代理方式:
- jdk动态代理: 面向接口
- cglib动态代理:面向无接口
jdk动态代理
java动态代理类位于java.lang.reflect.Proxy包下,创建代理类对象的方式是:
1. 创建被代理的类以及接口
2. 创建一个实现接口InvocationHandler的类,也就是处理器对象,它必须实现invoke方法
3. 通过Proxy的静态方法 newProxyInstance(ClassLoaderloader, Class[] interfaces, InvocationHandler h)创建一个代理对象
4. 通过代理对象调用方法
创建处理器对象类源码参数说明:
实现InvocationHandler类,重写invoke方法
/**
invoke方法参数说明
* public Object invoke(Object obj, Object... args)
* 反射机制
* obj 被代理的对象(实际的对象)
* args method方法的参数
*/
创建代理对象源码及参数说明:
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces, InvocationHandler h)
throws IllegalArgumentException
{
....
}
参数说明:
/*
* static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
* 返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。
* 参数:
* ClassLoader loader:传递类加载器,加载类到内存中,创建class文件对象;可以传递本类的类加载器
* Class<?>[] interfaces:传递ArrayList实现的接口List/Collection的Class文件对象
* InvocationHandler h:创建一个InvocationHandler的实现类,重写接口中的方法invoke,对集合的方法进行判断
* 如果调用add方法,没有对集合进行修改,则允许执行
* 返回值类型:
* Object:返回被代理后的方法返回值
*/
一个小栗子说明动态代理的实现过程:
- 首先我们要定义一个接口:
/**
* 接口
* @author wuqiong
*
*/
public interface IStudent {
public void study();
public int totalCourse(String name);
}
定义一个实现类,实现这个接口:
/**
* 实现接口,重写方法
* @author wuqiong
*
*/
public class StudentImpl implements IStudent {
public void study() {
System.out.println("学生学习...");
}
public int totalCourse(String name) {
return 9;
}
}
利用java反射机制,创建处理器对象。真实对象需要实现InvocationHandler接口,重写invoke()方法。
处理器对象如下:
/**
* 处理器对象,反射机制
* @author wuqiong
*
*/
public class JDKDynamicInvocation implements InvocationHandler{
private Object target;
public JDKDynamicInvocation(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 增强方法在真正方法执行之前执行
before();
Object result = method.invoke(target, args);
// 增强方法在真正方法执行之前执行
after();
return result;
}
/**
* 增强方法
*/
public void before() {
System.out.println("起床去上学...");
}
/**
* 增强方法
*/
public void after() {
System.out.println("骑自行车放学");
}
}
下面是对代理类对象的测试:
/**
* 动态代理类方法测试
* @author wuqiong
*
*/
public class JDKProxyTest{
public static void main(String[] args) {
// 创建真实对象
IStudent student = new StudentImpl();
// 创建处理器对象,将真实对象作为参数传给处理器对象
JDKDynamicInvocation jdkDynamicProxcy = new JDKDynamicInvocation(student);
// 创建代理类对象
IStudent studentProxy = (IStudent) Proxy.newProxyInstance(student.getClass().getClassLoader(),
student.getClass().getInterfaces(), jdkDynamicProxcy);
// 执行代理了对象的study()方法
studentProxy.study();
}
}
打印结果如下:
起床去上学...
学生学习...
骑自行车放学
我们可以看到,在执行study()方法之前执行了before()方法,打印“起床去上学…”,执行study()方法之后执行了after()方法,打印“骑自行车放学”。
老大让我干活了。下次继续。。。