使用JDK和CGLIB实现动态代理

在讲正题之前,先了解一下代理模式,非常形象逼真的买房子实例又要来了。

A去买房子,让B房屋中介公司负责相关事宜,比如看房子结构地段和卖房公司商量价格等等(没买过房子 乱讲的)

那么此时具体去买房子所要做的事情本来该是A做的,因为他要买房啊,但是却交给了B来管,

此时,A是被代理对象,B为代理对象

 

代理模式可以分为:远程代理,虚拟代理,保护代理,智能引用代理

代理模式的实现方法为;静态代理和动态代理

 

其中静态代理又分为 继承代理和聚合代理,在这就不敞开叙述了,一般情况下,采用聚合代理居多

 

 


 

使用JDK和CGLIB的区别

JDK只能代理实现了接口的类,如果没有实现接口的类则不能实现jdk动态代理

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

也就是说,CGLIB不能代理用final修饰的类

 

 

 

 

下面讲 如何使用JDK代理实现动态代理

 

实现步骤:

1. 创建一个实现接口InvocationHandler的类,必须实现invoke方法,在invoke方法中放我们的业务逻辑处理

2.创建被代理的类以及接口(类必须实现接口)

3.在mian中调用Proxy静态方法,创建一个代理类

 

具体的实现过程:通过newProxyInstance返回代理对象

(1)声明一段源码,动态的产生代理

(2)编译源码(JDK Compiler API),产生新的类,也就是代理类

(3)将这个类load到内存当中,产生一个新的对象,也就是代理对象

(4)return 代理对象

 

4.通过代理调用方法

 

代码示例:

 

接口:

 

public interface Moveable {
	void move();
}

 

 

 

 

 

 

 

实现类:

 

 

public class Car implements Moveable {

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

}

 

 

 

 

 

 

 

 

 

 

事务处理类:

 

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

}

 

 

 

 

 

 

 

 

测试类:

 

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import com.imooc.proxy.Car;
import com.imooc.proxy.Moveable;

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

}

 

 

 

 

 

 


此时如果想在时间处理事务的基础上添加其他处理,比如日志记录,则可再写一个实现了InvocationHandler接口的

LogHandler类,注意在Main方法中,添加loghandler时,可以选择先输出log还是时间

注意是哪个放在后面,就先执行哪个

 

public class Test {
	public static void main(String[] args) {
		
		/**
		 * 先Log后Time
		 */
		Car c=new Car();
		InvocationHandler h=new TimeHandler(c);
		Class<?> cla=c.getClass();
		Moveable m=(Moveable) Proxy.newProxyInstance(cla.getClassLoader(), cla.getInterfaces(), h);
		
		InvocationHandler h2=new LogHandler(m);
		Moveable m2=(Moveable) Proxy.newProxyInstance(cla.getClassLoader(), cla.getInterfaces(), h2);
		m2.move();
		
		
		/**
		 * 先Time后Log
		 */
		Car c=new Car();
		InvocationHandler h=new LogHandler(c);
		Class<?> cla=c.getClass();
		Moveable m=(Moveable) Proxy.newProxyInstance(cla.getClassLoader(), cla.getInterfaces(), h);
		
		InvocationHandler h2=new TimeHandler(m);
		Moveable m2=(Moveable) Proxy.newProxyInstance(cla.getClassLoader(), cla.getInterfaces(), h2);
		m2.move();
	
	}
}

 

 

 

 

 


Log先的输出:

 

 

 

log start!

start
end  10008
log end!

 

 

 

 

 

 

CGLIB实现动态代理

 

被代理类:

 

public class Car {
	public void move(){
		System.out.println("moving...");
	}
}

 

 

 

 

 

 

事务处理:

 

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

 

 

 

 

 

 

 

测试类:

 

public class Test {
	public static void main(String[] args) {
		CglibProxy proxy = new CglibProxy();
		Car t = (Car)proxy.getProxy(Car.class);
		t.move();
	}
}

 

 

 

 

 

 

 

 

输出:


日志开始...
moving...
日志结束...
 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值