代理模式

1.定义
为其它对象提供一种代理以控制对这个对象的访问。
2.应用场景
1)Spring AOP。Spring AOP底层就是使用动态代理来实现的,Spring将切面织入到代理对象中。
Spring AOP :[url] http://frank1234.iteye.com/blog/2170678[/url]
2)Hibernate延迟加载。Hibernate提供了延迟加载机制,使用延迟加载时先返回的就是真实对象的代理类,当真正请求的时候才调用真实对象到数据库中加载数据。
Hibernate检索策略: http://frank1234.iteye.com/blog/2174120
3)可以在代理类中加入权限验证,记录日志,统计计数器(这个同装饰者模式相同),运行时间统计等等。

3.类图

代理模式_第1张图片

1)Eatable:定义代理和真实对象统一的接口,这样保证使用真实对象的时候都可以使用代理类。
2)LazySheepProxy:代理类,控制对真实对象的访问,负责创建真实对象,维护指向真实对象的引用,负责访问真实对象。
3)LazySheep:真实对象,负责具体执行。
4)ProxyMain:客户端

4.代码示例
public interface Eatable {
   void eat();
}

public class LazySheep implements Eatable {
   public LazySheep(){
   }
   public void eat(){
      System.out.println("我是懒羊羊,我就是喜欢吃,我是吃货!");
   }
}

public class LazySheepProxy implements Eatable {
  private LazySheep real = null;
   public void eat(){
      if(real == null){
         real =  new LazySheep();
      }
      washhand();
     real.eat();
   }
   private void washhand(){
      System.out.println("我爱洗手,吃之前要洗手");
   }
}

public class ProxyMain {
   public static void main(String[] args) throws Exception{
      Eatable lazySheep = new LazySheep();
      lazySheep.eat();
      System.out.println("\n-------------我是分隔线--------------------------\n");
      Eatable lazySheepProxy = new LazySheepProxy();
      lazySheepProxy.eat();
   }
}

输出结果:
我是懒羊羊,我就是喜欢吃,我是吃货!

-------------我是分隔线--------------------------

我爱洗手,吃之前要洗手
我是懒羊羊,我就是喜欢吃,我是吃货!



5.JDK动态代理
public class JdkProxyLazySheep {
    public static Eatable getProxy(final Eatable realSubject) {

//创建动态代理
        return (Eatable) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(), new Class[]{Eatable.class},
                new InvocationHandler() {

                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        washhand();
//调用真实对象
                        Object retVal = method.invoke(realSubject, args);
                        System.out.println("action after method invocation....\n");
                        return retVal;
                    }
                });
    }
    private static void washhand(){
        System.out.println("我爱洗手,吃之前要洗手");
    }
}

    public static void main(String[] args) {
        //设置此系统属性,以查看代理类文件
//        System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");

        //创建代理对象
         Eatable proxy = JdkProxyLazySheep.getProxy(new LazySheep());
         proxy.eat();
    }
}
输出结果:
我爱洗手,吃之前要洗手
我是懒羊羊,我就是喜欢吃,我是吃货!
action after method invocation....

6.CGLib动态代理
public class CglibInterceptor implements MethodInterceptor{
   Object real = null;
   public Object intercept(Object obj, Method method, Object[] args,
         MethodProxy proxy) throws Throwable {
      washhand();
      return proxy.invokeSuper(obj, args);
   }
   public Object createCglibproxy(Object real){
      this.real = real;
      Enhancer enhance = new Enhancer();
      enhance.setSuperclass(this.real.getClass());
      enhance.setCallback(this);
      return enhance.create();
   }
   private void washhand(){
      System.out.println("我爱洗手,吃之前要洗手");
   }
}

public class CglibProxyMain {
    public static void main(String[] args ) throws Exception{
        Eatable proxy = (Eatable) new CglibInterceptor().createCglibproxy(new LazySheep());
        proxy.eat();
    }
}
输出结果:
我爱洗手,吃之前要洗手
我是懒羊羊,我就是喜欢吃,我是吃货!

7.代理模式与装饰者模式
代理模式和装饰者模式有时候看起来很相似,都可以在真实对象的方法前后添加行为,但是两者的目的不同,代理模式是为了控制对真实对象的访问,而装饰者模式是为了给对象添加职责。Proxy不像Decorator可以递归组合,代理对象和具体对象是静态的,而装饰者和具体对象之间的组合是动态的,需要在运行时动态组合。

你可能感兴趣的:(设计模式,动态代理,代理模式)