设计模式 - 代理模式

JDK动态代理

 1. 目的:动态产生代理,实现对【不同类】,【不同方法】的代理
 2. 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):
返回代理类的一个实例,返回后的代理类可以被当作代理类使用(可使用被代理类的在【接口中】声明过的方法)。
第一个参数loader为被代理类的加载器,通过被代理类.getClass().getClassLoader()得到·
第二个参数interfaces为被代理类实现的所有接口,同样通过getClass().getInterfaces()得到
第三个参数handler就是自己实现的InvocationHandler的实现类的对象

3. 动态代理实现:
1) 声明一个代理h实现InvocationHandler接口,通过【构造方法接受被代理类】,
并实现invoke方法,添加业务逻辑(实现原有功能并添加额外功能)
2) 在测试类中,通过共同实现接口的实例获得代理对象,并实现方法,
如Interface1 i = (Interface1)Proxy.newProxyInstance(classLoader,classInterfaces,h);
3) 通过动态代理对象m,代用其方法i.fun();

Moveable.java类

package com.goldmei.jdkproxy;

public interface Moveable {
	void move();
}
Car.java类

package com.goldmei.jdkproxy;

import java.util.Random;

public class Car implements Moveable {

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

}
TimeHandler.java类

package com.goldmei.jdkproxy;

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;
	
	/*
	 * 参数:
	 * proxy  被代理对象
	 * method  被代理对象的方法
	 * args 方法的参数
	 * 
	 * 返回值:
	 * Object  方法的返回值
	 * */
	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		long starttime = System.currentTimeMillis();
		System.out.println("汽车开始行驶....");
		method.invoke(target);
		long endtime = System.currentTimeMillis();
		System.out.println("汽车结束行驶....  汽车行驶时间:" 
				+ (endtime - starttime) + "毫秒!");
		return null;
	}

}
Test.java类

package com.goldmei.jdkproxy;

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


public class Test {

	/**
	 * JDK动态代理测试类
	 */
	public static void main(String[] args) {
		Car car = new Car();
		InvocationHandler h = new TimeHandler(car);
		Class<?> cls = car.getClass();
		/**
		 * loader  类加载器
		 * interfaces  实现接口
		 * h InvocationHandler
		 */
		Moveable m = (Moveable)Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(), h);
		m.move();
	}

}


JDK与CGLIB动态代理的区别
1、JDK:针对接口
· 只能代理【实现了接口的类】
· 没有实现接口的类不能实现JDK的动态代理
2、CGLIB:针对类
· 针对类来实现代理的
· 对指定目标类产生一个子类(覆盖其中的方法,来实现功能的增强),通过方法拦截技术拦截所有父类方法的调用
 . 因为是采用继承的方式,所以不能对final类型的类进行代理。
二、CGLIB:是一个强大的开源项目,可以在运行期扩展Java类与实现Java接口。

CglibProxy.java类

package com.goldmei.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();
	}
	
	/**
	 * 拦截所有目标类方法的调用
	 * obj  目标类的实例
	 * m   目标方法的反射对象
	 * args  方法的参数
	 * proxy代理类的实例
	 */
	@Override
	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;
	}

}

Train.java类

package com.goldmei.cglibproxy;

public class Train {

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

Client.java类

package com.goldmei.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();
	}

}

cglib-nodep-2.2.jar下载


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值