您的位置:首页 > 编程语言 > Java开发

Java代理模式

2015-06-15 14:05 519 查看
代理模式的定义: 为其他对象提供一种代理以控制对这个对象的访问。代理对象起到中介作用,可以去掉功能服务或者添加额外的服务

静态代理: 代理和被代理对象在代理之前是确定的。他们都实现相同的接口或者继承相同的抽象类

UML图:



以聚合代理的方式实现静态代理为例:
首先抽象接口

package proxy;

public interface Moveable {
void move();
}


被代理对象

package proxy;

import java.util.Random;

public class Car implements Moveable {

public void move() {
try {
Thread.sleep(new Random().nextInt(1000));
System.out.println("汽车行驶.....");
} catch (InterruptedException e) {
e.printStackTrace();
}
}

}


代理类1:

package proxy;

public class CarLogProxy implements Moveable {

public CarLogProxy(Moveable m) {
super();
this.m = m;
}

private Moveable m;

public void move() {
System.out.println("Log开始");
m.move();
System.out.println("Log结束");
}

}


代理类2:

package proxy;

public class CarTimeProxy implements Moveable {

public CarTimeProxy(Moveable m) {
super();
this.m = m;
}

private Moveable m;

public void move() {
System.out.println("计时开始");
m.move();
System.out.println("计时结束");
}

}


测试:

package proxy;

public class Client {

public static void main(String[] args) {
Car car = new Car();
CarLogProxy clp = new CarLogProxy(car);
CarTimeProxy ctp = new CarTimeProxy(clp);
ctp.move();
}

}


运行结果:
计时开始
Log开始
汽车行驶.....
Log结束
计时结束


但静态代理只能代理一种类型的被代理类,换个类型的就不行了,这需要动态代理

Java动态代理类位于java.lang.reflect包下,一般主要涉及到以下两个类:
(1)Interface InvocationHandler : 该接口中定义了一个方法
public object invoke(Object obj , Method method , Object[] args)
在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,args为该方法的参数数组。这个抽象方法在代理类中动态实现。
(2) Proxy : 该类即为动态代理类
static Object newProxyInstance(ClassLoader loader , Class[] interfaces , InvocationHandler h) : 返回代理类的一个实例, 返回后的代理类可以当作被代理类使用

动态代理实现步骤
(1)创建一个实现接口InvocationHandler的类,它必须实现invoke方法
(2)创建被代理的类以及接口
(3)调用Proxy的静态方法,创建一个代理类
newProxyInstance(ClassLoader loader , Class[] interfaces , InvocationHandler h)
(4) 通过代理调用方法
例:
抽象接口

package proxy;

public interface Moveable {
void move();
}


被代理类:

package proxy;

import java.util.Random;

public class Car implements Moveable {

public void move() {
try {
Thread.sleep(new Random().nextInt(1000));
System.out.println("汽车行驶....");
} catch (InterruptedException e) {
e.printStackTrace();
}
}

}


InvocationHandler 实现类

package proxy;

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

public class TimeHandler implements InvocationHandler {

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

private Object target;

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

System.out.println("计时前");
method.invoke(target);
System.out.println("计时后");
return null;
}

}


测试:

package proxy;

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

import proxy.Car;
import proxy.Moveable;

public class Test {

public static void main(String[] args) {
Car car = new Car();
InvocationHandler h = new TimeHandler(car);
Class<?> cls = car.getClass();

Moveable m = (Moveable)Proxy.newProxyInstance(cls.getClassLoader(),
cls.getInterfaces(), h);
m.move();
}

}


运行结果:

计时前
汽车行驶....
计时后


除了使用JDK实现动态代理之外,还可以使用CGLIB实现 ,需要引入cglib的jar包

被代理类:

package cglibproxy;

public class Train {

public void move(){
System.out.println("汽车行驶...");
}
}


代理类:

package cglibproxy;

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();
}

public Object intercept(Object obj, Method m, Object[] args,
MethodProxy proxy) throws Throwable {
System.out.println("代理开始..");
//调用父类方法
proxy.invokeSuper(obj, args);
System.out.println("代理结束...");
return null;
}

}


测试:

package cglibproxy;

public class Client {

/**
* @param args
*/
public static void main(String[] args) {

CglibProxy proxy = new CglibProxy();
Train t = (Train)proxy.getProxy(Train.class);
t.move();
}

}


运行结果:

代理开始..
汽车行驶...
代理结束...


两种动态代理的区别
JDK动态代理:
(1) 只能代理实现了接口的类;
(2)没有实现接口的类不能实现JDK的动态代理。

CGLIB动态代理:
(1) 针对类来实现代理的;
(2)对指定目标类产生一个子类, 通过方法拦截技术拦截所有的父类方法的调用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: