Java代理模式

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

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


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)对指定目标类产生一个子类, 通过方法拦截技术拦截所有的父类方法的调用。





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值