上文讲述了静态代理,jdk自身也实现了代理机制----jdk动态代理,需要应用jdk动态代理,需要实现一个接口java.lang.reflect.InvocationHandler,这样生成的动态代理就会自动调用invoke方法。代理要首先创建出来目标对象的代理对象,这个调用Proxy的newProxyInstance方法即可。
类似上文的需求,如果乙需要实现增删改查功能,但是实现之后这些功能要加安全性检查,但是不能动源代码,那么就可以用jdk动态代理实现,但是此时不再用实现与乙一样的接口了,只需要实现InvocationHandler接口即可,由于当业务方法被调用的时候实际都会调用invoke方法,这样在invoke方法中追加安全性检查代码就实现了不动源代码实现功能的目的,代码示例如下:
乙接口:
package com.DynamicProxy;
/**
* @author
*
* 2012-10-17上午9:37:31
*/
public interface ManagerInterface {
public void add();
public void delete();
public void modify();
public String search();
}
乙实现:
package com.DynamicProxy;
/**
* @author
*
* 2012-10-17上午9:38:26
*/
public class ManagerImpl implements ManagerInterface {
public void add() {
System.out.println("add");
}
public void delete() {
System.out.println("delete");
}
public void modify() {
System.out.println("modify");
}
public String search() {
System.out.println("search");
return "search=============================";
}
}
动态代理:
package com.DynamicProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @author
*
* 2012-10-17上午10:04:41
*/
public class ManagerProxy implements InvocationHandler {
Object targetObject;
public Object newProxy(Object targetObject) {
this.targetObject = targetObject;
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
targetObject.getClass().getInterfaces(), this);
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
checkSecurity();
Object ret = null;
try {
ret = method.invoke(targetObject,args);
} catch (Exception e) {
e.printStackTrace();
}
return ret;
}
public void checkSecurity(){
System.out.println("checkSecurity==============================");
}
}
客户端代码:
package com.DynamicProxy;
/**
* @author
*
* 2012-10-17上午10:20:50
*/
public class Client {
/**
* @param args
*/
public static void main(String[] args) {
ManagerImpl managerImpl = new ManagerImpl();
ManagerProxy managerProxy = new ManagerProxy();
ManagerInterface managerInterface = (ManagerInterface)managerProxy.newProxy(managerImpl);
managerInterface.add();
managerInterface.delete();
managerInterface.modify();
System.out.println(managerInterface.search());
}
}
需要注意的是
调用invoke方法时候的第一个参数为目标对象引用,如果此处直接 method.invoke(proxy,args);就会有问题了,proxy是jdk为你生成的代理类的实例,实际上就是使用代理之后adder引用所指向的对象。由于我们调用了managerInterface.add(),才使得invoke()执行,如果在invoke()中使用method.invoke(proxy, args),那么又会使invoke()执行。没错,这是个死循环。
具体代码见附件。