程序的代理模式:
当一个对象不能直接操作另一个对象时采用代理(Proxy)模式。在代理模式中可以添加一些其他业务逻辑如:日志操作、权限控制等。
代理的实现方式有两种:
1.静态代理:通过程序硬编码,为目标类做一层封装,但最终操作的还是目标类;
2.动态代理:在运行期生成目标对象的代理对象。
本为主要讲述动态代理的两种实现方式:JDK动态代理、CGLIB动态代理。
实例:
A.定义目标类与其扩展的接口
//定义一个学习接口
package phda.proxy;
public interface Study {
public void study(String name);//提供一个学习方法
}
//其扩展类
package phda.proxy;
public class Robot implements Study {
public void study(String name) {
System.out.println("机器人 :"+name+" learn");
}
}
B.JDK动态代理实现:
package phda.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* jdk 动态代理测试
* @author Administrator
*
*/
public class JDKProxy {
public static Object getProxyObject(final Object c){
return Proxy.newProxyInstance(c.getClass().getClassLoader(),//目标类的classLoader
c.getClass().getInterfaces(), //目标类有实现的接口
new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("可以定义一些其他业务操纵:日志操作");
System.out.println("JDK代理实现:"+method.getName());
return method.invoke(c, args);
}
});
}
public static void main(String[] args) {
Robot r = new Robot();//这是直接获得对象
//r.study("jiqiren");
Study r2 =(Study)JDKProxy.getProxyObject(r);//获得一个代理对象
r2.study("代理对象");
}
}
说明:
1.使用jdk 动态代理,目标类必须要有扩展的接口;
2.代理生成的对象,为目标类扩展接口第一个接口的类型的对象,如上面的接口“Study”;==>t.getClass().getInerfaces() 数组中的第一个元素
打印结果:
可以定义一些其他业务操纵:日志操作
JDK代理实现:study
机器人 :代理对象 learn
C.CGLIB代理实现:
package phda.proxy;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
/**
* cglib 代理
* @author Administrator
*
*/
public class CGLIBObject {
public static Object getPoxyObject(Object c) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(c.getClass());
enhancer.setCallback(new MethodInterceptor() {
public Object intercept(Object arg0, Method arg1, Object[] arg2,
MethodProxy arg3) throws Throwable {
System.out.println("CGLIB动态代理:"+arg1.getName());
arg3.invokeSuper(arg0, arg2);
return null;
}
});
return enhancer.create();
}
public static void main(String[] args) {
Robot r = new Robot();
Study r2 =(Robot) CGLIBObject.getPoxyObject(r);
r2.study("nini");
}
}
说明:
1.这种代理没有接口的限制;
2.代理生成的对象可以是目标对象类型,也可以是接口的扩展类型;
资源下载
动态代理实例下载
补充:
代理模式的优点:
在不该改变被代理类的基础上,对已有的类进行功能扩展或附加。例如:权限控制、日志记录等
动态代理与静态代理之间的区别:
静态代理,以编码的方式需要实现被代理类的各个方法,这样做增加了编码量;动态代理,可以将生成代理类的方法写成公共方法,只需要传递类(xx.class)就可以获取到对应的被代理对象。同时,不用逐个编写被代理类的方法。有现成的生成代理的类,使代理模式实现更加简单,让我们更加关注业务。
动态代理 | 静态代理 | |
---|---|---|
逐个实现被代理类的方法 | 需要 | 不需要 |
编码量 | 小 | 大 |
灵活度 | 高 | 低 |
【灵活度:采用静态代理,要为每个被代理类写响应的代理类,而动态代理不需要】