转:http://blog.csdn.net/zsmj_2011/article/details/10394805
代理模式是一种应用非常广泛的设计模式,当客户端代码需要调用某个对象时,客户端实际上不关心是否准确得到该对象,它只要一个能提供该功能的对象即可,此时,我们就可以返回该对象的代理。
通常情况下,适用代理模式的情况有两种:
1.创建对象开销很大,可以创建一个代理对象,推迟真正的对象创建。大家所熟悉的Hibernate延迟加载策略就是使用动态代理,当A实体关联B实体时,在获取A实体时不需要立即获得与A实体关联的B实体,因为有可能客户端根本不需要B实体数据,当客户端真正需要这部分数据时,再加载B实体的数据。这样就节省了资源。
2.所创建的对象不能满足客户端需求,比如说我们需要为某个方法运行前加入一些验证或者过滤,这时我们就需要创建一个代理对象,增强原来对象的功能。
java实现动态代理有两种方法:jdk代理和cglib。
jdk动态代理
jdk代理需要使用一个接口(
InvocationHandler)和一个类(
Proxy)
InvocationHandler接口定义如下:
- public interface InvocationHandler {
- public Object invoke(Object proxy,Method method,Object[] args) throws Throwable;
- }
代理类要实现这个接口,并实现Invoke方法,这个就是代理方法,当客户端调用委托对象方法时,实际上执行Invoke方法。
Proxy类提供了静态方法来获取动态代理对象:
- public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,
- InvocationHandler h) throws IllegalArgumentException
下面看一个jdk动态代理的例子:
首先定义一个接口
- public interface IPerson {
-
- void walk();
- }
定义实现类
- public class Person implements IPerson {
-
- @Override
- public void walk() {
- System.out.println("walk");
- }
-
- }
定义代理实现类
- public class MyInvokationHandler implements InvocationHandler {
-
- private Object target;
- public void setTarget(Object target) {
- this.target=target;
- }
-
-
-
-
-
-
- @Override
- public Object invoke(Object proxy, Method method, Object[] args)
- throws Throwable {
- System.out.println("正在执行的方法:"+method);
- method.invoke(target, args);
- return null;
- }
-
- }
main函数
- public class ProxyTest {
-
-
-
-
- public static void main(String[] args) {
-
- MyInvokationHandler handler =new MyInvokationHandler();
- Person person=new Person();
- handler.setTarget(person);
- IPerson p=(IPerson)Proxy.newProxyInstance(Person.class.getClassLoader(), Person.class.getInterfaces(), handler);
- p.walk();
- }
-
- }
这就是jdk动态代理的基本用法,是不是显的很麻烦,必须要使用接口,如果程序很简单,不想用接口,那么就不能使用jdk动态代理技术。
为什么jdk动态代理必须要使用接口呢?
原因是,jdk动态代理实际是要根据接口创建新的实现类,来实现代理方法。那么对于不是面向接口编程的程序,就无法使用jdk动态代理了,这时cglib解决了这个问题,cglib使用继承来创建代理类,因此可以传入普通类而不是接口来实现代理类,但是对于final类,无法实现动态代理。
cglib动态代理
和jdk动态代理使用方法类似,示例如下:
1、创建一个实现net.sf.cglib.proxy.MethodInterceptor接口的实例来为目标业务类加入进行代理时要进行的操作或增强:
- import java.lang.reflect.Method;
- import net.sf.cglib.proxy.MethodProxy;
- import net.sf.cglib.proxy.Enhancer;
- import net.sf.cglib.proxy.MethodInterceptor;
-
-
-
-
-
- public class CglibProxy implements MethodInterceptor{
- private Enhancer enhancer = new Enhancer();
-
- public Object getProxy(Class clazz){
- enhancer.setSuperclass(clazz);
- enhancer.setCallback(this);
- return enhancer.create();
- }
-
- public Object intercept(Object obj,Method method,Object[] args,
- MethodProxy proxy) throws Throwable {
- System.out.println("模拟代理增强方法");
-
-
- Object result = proxy.invokeSuper(obj, args);
-
- System.out.println("模拟代理增强方法结束");
- return result;
- }
- }
2、通过java.lang.reflect.Proxy的getProxy()动态生成目标业务类的子类,即是代理类,再由此得到代理实例:
- import com.proxy.ForumServiceImpl;
- import java.lang.reflect.Proxy;
-
- public class TestCglibProxy {
- public static void main(String args[]){
- CglibProxy proxy = new CglibProxy();
-
-
- ForumServiceImpl fsi =
- (ForumServiceImpl)proxy.getProxy(ForumServiceImpl.class);
-
- fsi.removeForum(10);
- fsi.removeTopic(2);
- }
- }