Proxy提供了用于创建动态代理类和代理对象的静态方法,它也是所有动态代理类的父类。如果在程序中为一个或多个接口动态的生成实现类,
就可以使用Proxy来创建动态代理类;如果需要为一个或多个接口动态地创建实例,也可以使用Proxy来创建动态代理实例。
Proxy提供了如下两个方法来动态创建代理类和动态代理实例。
(1) static Class<?> getProxyClass(ClassLoder loader, Class<?>...interfaces):创建一个动态代理类多对应的Class对象,该代理类实现将实现
interfaces所指定的多个接口。第一个ClassLoader参数指定生成动态代理类的类加载器。
(2) static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h):直接创建一个动态代理对象,该代
理对象对象的实现类实现了interfaces指定的系列接口,执行代理对象的每个方法时都会替换成执行InvocationHandler对象的invoke方法。
实际上,即使采用第一个方法生成动态代理类之后,如果程序需要通过该代理类来创建对象,依然需要传入一个Invocationhandler对象。也就
是说,系统生成的每个代理对象都有一个与之关联的Invocationhandler对象。例如下面的代码:
// 创建一个InvocationHandler对象,其中MyInvocationHandler是实现InvocationHandler接口的类
InvocationHandler handler = new MyInvocationHandler();
// 使用Proxy生成一个动态代理类proxyClass
Class proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(), new Class[]{Foo.class});
// 获取proxyClass类中带有一个InvocationHandler参数的构造器
Constructor ctor = proxyClass.getConstructor(new Class[]{Invocationhandler.class});
// 调用ctor的newInstance方法来创建动态实例
Foo f = (Foo) ctor.newInstance(new Object[]{Handler});
下面程序示范了使用Proxy和InvocationHandler来生成动态代理对象。其目的是:对需要代理的对象的每个方法的开始和结束打印一行日志
信息:
ArithmeticCalculatorloggingImpl.java:
package com.yu.spring.aop.helloworld;
public class ArithmeticCalculatorImpl implements ArithmeticCalculator {
@Override
public int add(int i, int j) {
int result = i + j;
return result;
}
@Override
public int sub(int i, int j) {
int result = i - j;
return result;
}
@Override
public int mul(int i, int j) {
int result = i * j;
return result;
}
@Override
public int div(int i, int j) {
int result = i / j;
return result;
}
}
ArithmeticCalculatorLoggingProxy.java:
package com.yu.spring.aop.helloworld;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
public class ArithmeticCalculatorLoggingProxy {
// 要代理的对象
private ArithmeticCalculator target;
public ArithmeticCalculatorLoggingProxy(ArithmeticCalculator target) {
this.target = target;
}
public ArithmeticCalculator getLoggingProxy(){
ArithmeticCalculator proxy = null;
// 代理对象由哪一个类加载器负责加载
ClassLoader loader = target.getClass().getClassLoader();
// 代理对象的类型,即其中有哪些方法
Class[] interfaces = new Class[]{ArithmeticCalculator.class};
// 当调用代理对象其中的方法时,该执行的代码
InvocationHandler h = new InvocationHandler(){
/**
* 执行动态代理对象的所有方法时,都会替换成执行如下的invoke方法,其中:
* proxy:正在返回的代理对象,一般情况下,在invoke方法中都不使用该对象
* method:正在被调用的方法
* args:调用方法时,传入的参数
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
// 日志
System.out.println("the method " + methodName + " begins with " + Arrays.asList(args));
// 执行方法
Object result = method.invoke(target, args);
// 日志
System.out.println("The method " + methodName + " ends with " + Arrays.asList(args));
return result;
}
};
proxy =(ArithmeticCalculator) Proxy.newProxyInstance(loader, interfaces, h);
return proxy;
}
}
测试类Main.java:
package com.yu.spring.aop.helloworld;
public class Main {
public static void main(String[] args) {
// ArithmeticCalculator ac = null;
// ac = new ArithmeticCalculatorImpl();
ArithmeticCalculator target = new ArithmeticCalculatorImpl();
ArithmeticCalculator proxy = new ArithmeticCalculatorLoggingProxy(target).getLoggingProxy();
int result = proxy.add(1, 2);
System.out.println("-->" + result);
result = proxy.sub(4, 1);
System.out.println("-->" + result);
result = proxy.mul(2, 3);
System.out.println("-->" + result);
result = proxy.div(7, 3);
System.out.println("-->" + result);
}
测试结果: