Java 的动态代理模式

代理模式(Proxy)

其实JAVA 的每个模式名称就表明了该模式的作用,代理模式就是多一个代理类出来,替原对象进行一些操作,比如我们在租房子的时候回去找中介,为什么呢?因为你对该地区房屋的信息掌握的不够全面,希望找一个更熟悉的人去帮你做,此处的代理就是这个意思。再如我们有的时候打官司,我们需要请律师,因为律师在法律方面有专长,可以替我们进行操作,表达我们的想法。

例码:

public interface Sourceable {
    public void method();
}

public class Source implements Sourceable {  
  
    @Override  
    public void method() {  
        System.out.println("the original method!");  
    }  
} 


public class Proxy implements Sourceable {  
  
    private Source source;  
    public Proxy(){  
        super();  
        this.source = new Source();  
    }  
    @Override  
    public void method() {  
        before();  
        source.method();  
        atfer();  
    }  
    private void atfer() {  
        System.out.println("after proxy!");  
    }  
    private void before() {  
        System.out.println("before proxy!");  
    }  
}  

代理模式的应用场景:

如果已有的方法在使用的时候需要对原有的方法进行改进,此时有两种办法:

1、修改原有的方法来适应。这样违反了“对扩展开放,对修改关闭”的原则。

2、就是采用一个代理类调用原有的方法,且对产生的结果进行控制。这种方法就是代理模式。

使用代理模式,可以将功能划分的更加清晰,有助于后期维护!

 

代理模式JAVA&Spring AOP 中的应用

 

代理的实现分动态代理和静态代理,静态代理的实现是对已经生成了的JAVA类进行封装。

动态代理则是在运行时生成了相关代理累,在JAVA中生成动态代理一般有两种方式。

一、JAVA 自带的代理实现:

JDK实现代理生成,是用类 java.lang.reflect.Proxy, 实现方式如下

public class JDKProxy {

      public static Object getPoxyObject(final Object c) {

            return Proxy.newProxyInstance(c.getClass().getClassLoader(), c.getClass().getInterfaces(),// JDK实现动态代理,但JDK实现必须需要接口

                        new InvocationHandler() {

                             public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                                    // TODO Auto-generated method stub

                                    Object reObj = null;

                                    System.out.print("you say: ");

                                    reObj = method.invoke(c, args);

                                    System.out.println(" [" + Calendar.getInstance().get(Calendar.HOUR) + ":"

                                                + Calendar.getInstance().get(Calendar.MINUTE) + " "

                                                + Calendar.getInstance().get(Calendar.SECOND) + "]");

                                    return reObj;

                              }

                        });

      }

}

1, Proxy实现代理的目标类必须有实现接口

2, 生成出来的代理类为接口实现类,和目标类不能进行转换,只能转为接口实现类进行调用

明显特点:通过此方法生成出来的类名叫做 $Proxy0

 

二、用 CGLIB 实现

public class CGLIBProxy {

      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 proxy) throws Throwable {

                        System.out.print("you say: ");

                        proxy.invokeSuper(arg0, arg2);

                        System.out.println(" [" + Calendar.getInstance().get(Calendar.HOUR) + ":"

                                    + Calendar.getInstance().get(Calendar.MINUTE) + " " + Calendar.getInstance().get(Calendar.SECOND)

                                    + "]");

                        return null;

                  }

            });

            return enhancer.create();

      }

}

1, CGLIB实现方式是对代理的目标类进行继承

2, 生成出了的代理类可以没方法,生成出来的类可以直接转换成目标类或目标类实现接口的实现类,因JAVA向上转换

明显特点:通过输出看出,看出生成出的代理类的parent类为代理的目标类

 

 

Spring AOP中,当拦截对象实现了接口时,生成方式是用JDK的Proxy类。当没有实现任何接口时用的是GCLIB开源项目生成的拦截类的子类.

posted @ 2017-02-04 11:22  Just4Me  阅读(295)  评论(0编辑  收藏  举报