Object java.lang.reflect.Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h) throwsIllegalArgumentException
Object java.lang.reflect.Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h) throwsIllegalArgumentException
Returns an instance of a proxy class for the specified interfaces that dispatches method invocations to the specified invocation handler
上面这句的意思是该方法返回一个指定接口的一个代理类, 这个接口将方法调用派遣到指定的调用句柄, 所谓invocation handler也就是代理。
很明显JDK中要被动态代理的类需要实现一个接口。
public class RobotProxy implements InvocationHandler {
private Object target;
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("Robot proxy access");
Object result = method.invoke(target, args);
System.out.println("Robot proxy leave");
return result;
}
public Object getInstance(Object target){
this.target = target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this);
}
}
使用代理
Robot robot = new Robot();
RobotProxy rProxy = new RobotProxy();
Language iRobot = (Language)rProxy.getInstance(robot);
iRobot.spell("hello world, my name is an intelegent ROBOT!");
这种代理返回的是接口类型
Robot iRobot = (Robot)rProxy.getInstance(robot);
改成上面代码后会报错
Exception in thread "main" java.lang.ClassCastException: $Proxy0 cannot be cast to Robot
at RobotTest.main(RobotTest.java:13)
CGLIB则是通过生成类的子类来实现的动态代理, 这样就允许不实现接口也能被代理。
public class RobotCglibProxy implements MethodInterceptor {
private Object target;
public Object getInstance(Object target){
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
System.out.println("Robot cglib proxy access");
Object result = proxy.invoke(target, args);
System.out.println("Robot cglib proxy leave");
return result;
}
}
为了测试我把接口去掉
public class Robot {
public void spell(String words) {
System.out.println(words);
}
public String getRobotName(){
return "Timi";
}
}
Robot robot = new Robot();
RobotCglibProxy rcProxy = new RobotCglibProxy();
Robot icRobot = (Robot)rcProxy.getInstance(robot);
icRobot.spell("hello world, my name is an intelegent ROBOT!");
System.out.println("Robot name is :"+icRobot.getRobotName());