疯狂java


您现在的位置: 疯狂软件 >> 新闻资讯 >> 正文

java代理模式


 

       1、静态代理

  由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。

  接口类:

  Java代码

  package org.lazyzhong.test;

  public interface People {

  public void speak();

  public void doWork();

  }

  实现类:

  Java代码

  package org.lazyzhong.test;

  public class Man implements People{

  @Override

  public void speak() {

  System.out.println("I am man");

  }

  @Override

  public void doWork() {

  System.out.println("I do work");

  }

  }

  代理类:

  Java代码

  package org.lazyzhong.test;

  public class PeopleProxy implements People{

  private Man man;

  public PeopleProxy() {

  super();

  }

  public PeopleProxy(Man man) {

  this.man = man;

  }

  @Override

  public void speak() {

  System.out.println("有请人类1/2的代表讲话。。。");

  man.speak();

  System.out.println("人类1/2的代表讲话完毕。。。");

  }

  @Override

  public void doWork() {

  }

  }

  测试类:

  Java代码

  People p=new PeopleProxy(new Man());

  p.speak();

  输出:

  有请人类1/2的代表讲话。。。

  I am man

  人类1/2的代表讲话完毕。。。

  2、动态代理

  在程序运行时,运用反射机制动态创建而成。

  2.1 jdk动态代理

  接口类,实现类和上面的一样。。。

  代理类:

  Java代码

  package org.lazyzhong.test;

  import java.lang.reflect.InvocationHandler;

  import java.lang.reflect.Method;

  import java.lang.reflect.Proxy;

  public class MyProxy implements InvocationHandler{

  private Object target;

  public Object bind(Object target){

  this.target=target;

  return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),this);

  }

  @Override

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

  throws Throwable { //方法中的Proxy不是target,是虚拟的实现类。

  Object result=null;

  System.out.println("事物开始");

  result=method.invoke(target, args);

  System.out.println("事物结束");

  return result;

  }

  }

  测试类:

  Java代码

  MyProxy proxy=new MyProxy();

  People p=(People)proxy.bind(new Man());

  p.speak();

  p.doWork();

  输出:

  事物开始

  I am man

  事物结束

  事物开始

  I do work

  事物结束

  JDK动态代理中包含一个类和一个接口:

  InvocationHandler接口:

  public interface InvocationHandler {

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

  }

  参数说明:

  Object proxy:指被代理的对象。

  Method method:要调用的方法

  Object[] args:方法调用时所需要的参数

  可以将InvocationHandler接口的子类想象成一个代理的最终操作类,替换掉ProxySubject。

  Proxy类:

  Proxy类是专门完成代理的操作类,可以通过此类为一个或多个接口动态地生成实现类,此类提供了如下的操作方法:

  public static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h) throws IllegalArgumentException

  参数说明:

  ClassLoader loader:类加载器

  Class[] interfaces:得到全部的接口

  InvocationHandler h:得到InvocationHandler接口的子类实例

  2.2 cglib动态代理:注意cglib是否和asm.jar版本冲突..这里用的是cglib-2.1.95和asm-3.3

  实现类:

  Java代码

  package org.lazyzhong.test;

  public class Man{ //注意并没有实现接口

  public void speak() {

  System.out.println("I am man");

  }

  }

  代理类:

  Java代码

  package org.lazyzhong.test;

  import java.lang.reflect.Method;

  import net.sf.cglib.proxy.Enhancer;

  import net.sf.cglib.proxy.MethodInterceptor;

  import net.sf.cglib.proxy.MethodProxy;

  public class MyCGProxy implements MethodInterceptor{

  private Object target;

  /**

  * 创建代理对象

  * @param target

  * @return

  */

  public Object getInstance(Object target){

  this.target=target;

  Enhancer enhancer = new Enhancer();

  enhancer.setSuperclass(this.target.getClass());

  // 回调方法

  enhancer.setCallback(this);

  // 创建代理对象

  return enhancer.create();

  }

  @Override

  public Object intercept(Object obj, Method method, Object[] args,

  MethodProxy proxy) throws Throwable {

  System.out.println("事物开始");

  proxy.invokeSuper(obj, args);

  System.out.println("事物结束");

  return null;

  }

  }

  测试:

  Java代码

  MyCGProxy pro=new MyCGProxy();

  Man man=(Man)pro.getInstance(new Man());

  man.speak();

  输出:

  事物开始

  I am man

  事物结束

  JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。