代理模式

1:代理模式定义

  为其他对象提供一种代理以控制对这个对象的访问,代理对象起到了中介作用,可去掉功能服务或者增加额外的服务。

2:静态代理 Static Proxy

  1)继承 extends

   子类继承父类,重写其相应方法,增加额外服务,实现代理功能 

  2)聚合 implements

   与被代理的类共同实现同一个接口,在代理类Proxy内部创建被代理类的对象,在被代理类对象调用相应方法的同时,增加额外的服务,实现代理功能。

    interface Moveable

    Class Car implements Moveable

    Class TimeProxy implements Moveable{

      Moveable moveable;

      创建含参moveable的构造方法,体现面向接口编程的思想

      在方法主体中添加代理功能和Moveable的主体方法

    }

  聚合比继承更适合代理模式,在代理类Proxy的内部使用面向接口编程,并没有指明具体的实现类,而且可以创建多个不同代理功能的代理类,例如日志代理,时间代理,在main方法中把他们联系起来便好,还可以在main方法中决定代理类的使用顺序。

3:动态代理

  1)JDK动态代理

  1] 创建一个实现接口InvocationHandler的类,它必须实现Invoke方法

  2]创建被代理的类以及接口

  3]调用Proxy的静态方法,创建一个代理类

  newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h)

  4]通过代理调用方法

  所谓代理,就是为了修改被代理对象的某些功能,日志代理,时间代理,就是添加了日志功能和时间功能,无谓继承还是聚合,静态代理同时对具体的被代理类进行功能上的修改。动态代理,顾名思义,是动态生成代理类的模式,重点在于把功能和代理区分开来。

  TimeHandler就是时间控制器,重写了InvocationHandler类实现了Invoke方法,它不再是某种具体代理类的功能,不再是CarTimeProxy,Time是功能,Proxy是代理。

  newProxyInstance()的参数invaocationHandler h 便是为代理类添加功能,至于前面的类加载器和接口,是为了生成具体的代理类,当代理和功能区分开来,便实现了解耦的目的。

  Dynamic Proxy是一种Class ,是运行时生成的class,需要实现一组interface。使用动态代理是,必须实现InvocationHandler接口。

  2)cglib动态代理

  cglib动态代理是针对类实现代理的,对指定目标类产生一个子类,通过方法拦截技术拦截所有父类方法的调用。

  JDK动态代理实现invocationHandler,cglib实现MethodIntercepter。

  JDK是向上找接口,用接口的抽象方法来替代未知的多种的具体被代理的方法,在此时添加功能。

  cglig是在父类方法调用的同时添加功能,运用了拦截器,是向下找子类。

  二者相同之处在于,具体的功能都与代理分离,功能都必须重写相应接口的抽象方法,JDK找接口很容易找到,但cglib必须指定给父类,也就是被代理的类。

  Enhancer负责设置创建子类的类,即代理类,建议写在MethodIntercepter接口的实现类中。

  综上:反射是Java中很重要的思想。

JDK:

  //Handler这个就是时间功能

  

package com.zhao.dynamic_proxy.jdk;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class TimeHandler implements InvocationHandler {
private Object object;

public TimeHandler(Object object) {
super();
this.object = object;
}

/*
* 参数:
* proxy:被代理的对象
* method:被代理对象的方法
* args:方法的参数
*
* 返回值:
* Object:方法的返回值
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// TODO Auto-generated method stub
long startTime = System.currentTimeMillis();
System.out.println("汽车开始行驶~~~");
method.invoke(object);
long endTime = System.currentTimeMillis();
System.out.println("汽车结束行使~~~");
System.out.println("汽车的行驶时间是:" + (endTime - startTime) + "毫秒");
return null;
}

}

 

  //创建代理

package com.zhao.dynamic_proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

import org.junit.Test;

import com.zhao.dynamic_proxy.jdk.TimeHandler;
import com.zhao.static_proxy.service.Moveable;
import com.zhao.static_proxy.service.impl.Car;

/*
* JDK动态代理测试类
* */
public class TestJDK {

@Test
public void test() {
Car car=new Car();
InvocationHandler h=new TimeHandler(car);
Class<?> cls=car.getClass();
/*
* loader:类加载器
* interfaces:实现接口
* h:InvocationHandler
* */
Moveable moveable=(Moveable)Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), h);
moveable.move();
}

}

 

Cglib:

  

package com.zhao.dynamic_proxy.cglib;

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 CglibProxy implements MethodInterceptor{
private Enhancer enhancer=new Enhancer();

public Object getProxy(Class clazz){
//设置创建子类的类
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);

return enhancer.create();
}

/*
* 拦截所有目标类方法的调用
* object:目标类的实例
* method:目标方法的反射对象
* args:方法的参数
* proxy:代理类的实例
* */
@Override
public Object intercept(Object object, Method method, Object[] args, MethodProxy proxy) throws Throwable {
// 代理类调用父类的方法
System.out.println("日志开始~~~~~~~~");
proxy.invokeSuper(object, args);
System.out.println("日志结束~~~~~~~~");
return null;
}

}

 

//获取代理类(代理类在上面的方法中创建)

package com.zhao.dynamic_proxy;


import org.junit.Test;
import com.zhao.dynamic_proxy.cglib.CglibProxy;
import com.zhao.dynamic_proxy.cglib.Train;

public class TestCglib {

@Test
public void test() {
CglibProxy cglibProxy=new CglibProxy();
Train train=(Train) cglibProxy.getProxy(Train.class);
train.move();
}

}

posted @ 2016-03-30 21:59  假寐的我  阅读(173)  评论(0编辑  收藏  举报