对于静态代理,如果接口发生改变,那么代理类和原始对象都要发生改变。而且每一个原始对象都需要一个代理类完成代理操作。因此类数目会相当多。
因此使用jdk动态代理时,动态代理类始终只有一个invoke方法,当接口发生改变时,动态代理的接口不用随之改变。但是要求目标对象必须实现接口,因为它创建代理对象的时候是根据接口创建的。如果不实现接口,jdk无法给目标对象创建代理对象。
动态代理现在只能代理接口,实现是依靠Java反射机制和动态生成class技术。而Spring的AOP也就是应用到jdk动态代理技术。
实例如下:依旧使用保护代理模拟权限控制
1、接口:
/**
* 由于使用jdk动态代理,必须依赖于实现接口
* @author cai.wuxin
*
*/
public interface OAOperate {
public void add();
public void select();
public void delete();
}
2、目标对象:
public class OAOperateImpl implements OAOperate{
private String name;
private int flag;
public OAOperateImpl(String name,int flag) {
this.name = name;
this.flag = flag;
}
public int getFlag(){
return this.flag;
}
@Override
public void add() {
//省略相应操作
}
@Override
public void select() {
//省略相应操作
}
/**
* delete需要权限设置
*/
@Override
public void delete() {
//省略相应操作
System.out.println("删除操作");
}
}
public class DynamicProxy implements InvocationHandler{
private OAOperateImpl operate = null;
public OAOperate getProxyInterface(OAOperateImpl operate){
this.operate = operate;
OAOperate oApi = (OAOperate)Proxy.newProxyInstance(
operate.getClass().getClassLoader(),
operate.getClass().getInterfaces(),
this);
return oApi;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// TODO Auto-generated method stub
if(method.getName().startsWith("delete")){
if(operate.getFlag()==4){
return method.invoke(operate, args);
}else{
System.out.println("权限不足");
}
}else{
return method.invoke(operate, args);
}
return null;
}
}
4、客户端实现:
public class Client {
public static void main(String []args){
OAOperateImpl o1 = new OAOperateImpl("lilei",3);
OAOperateImpl o2 = new OAOperateImpl("hanmeimei",4);
DynamicProxy dp1 = new DynamicProxy();
DynamicProxy dp2 = new DynamicProxy();
OAOperate proxy1 = dp1.getProxyInterface(o1);
OAOperate proxy2 = dp2.getProxyInterface(o2);
proxy1.delete();
proxy2.delete();
}
}
5、运行结果:
权限不足
删除操作
但是限制还是在于获得代理类必须依赖于接口。
更加深入的分析有关如何生成代理对象,代理对象如何代用invoke方法,本人还未深究。如果有感兴趣者可以查看源码或者参考以下文章:
http://rejoy.iteye.com/blog/1627405