Java的反射机制与动态代理(二):动态代理

原创
2017/03/28 16:37
阅读数 13

1. 为什么要使用动态代理?

在开发中我们会遇到这种情形,一个类中的方法随着业务的发展需要重新修改,而其他的方法还要使用该方法,遇到这种情形时该怎么做?举一个京东图书节促销的例子。假设所有的图书类(Book)都实现了IBook接口,在IBook接口中有一个方法getPrice,用于标识每一本书的价格,因为到了促销节会有很多的图书进行降价,但是在某个子程序中会调用原来的getPrice方法,因此,这个时候你不能贸然去修改原来的getPrice方法,避免其它模块不能正常工作。这个时候你可能会选择继承,创建一个新的类BookExtends继承自Book类,然后重新getPrice方法,由于getPrice方法没有提供额外的参数,因此在方法内你只能将促销价格固定,显然这种方式不可取,因为并不是每一本书的降价幅度都是一致的,为了解决这个问题,可以使用动态代理。

2. 如何使用动态代理?

还是以上面的例子,原始的业务处理过程如下程序所示:

package com.dd171290.proxy.book;

public interface IBook {
	float getPrice();
}
package com.dd171290.proxy.book;

public class ComputerBook implements IBook{

	public float getPrice() {
		return 100.0f;//计算机图书的原价为100元
	}
}

假设购买的图书有折扣,那么动态代理的方式:

package com.dd171290.proxy.book;

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

public class ComputerProxy {
	public static IBook getComputerProxy(final float discount) {
		Object object = Proxy.newProxyInstance(
				ComputerBook.class.getClassLoader(), //IBook实现类的类加载器
				new Class<?>[] { IBook.class },//实现类的接口
				new InvocationHandler() {//具体的处理类
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						//内部通过反射的机制来调用getPrice方法
						Object price = method.invoke(new ComputerBook(), args);
						return Float.parseFloat(price.toString()) - discount;
					}
				});
		return (IBook) object;
	}
}

测试效果:

package com.dd171290.proxy.book;

public class Test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//原来的方法
		ComputerBook book=new ComputerBook();
		System.out.println(book.getPrice());
		
		//通过代理的形式
		IBook test=ComputerProxy.getComputerProxy(20.0f);
		System.out.println(test.getPrice());
	}

}

-----------result------------------------------
100.0
80.0

此为动态代理的简单用法,通过源码来分析,内部是使用反射(reflect)完成的,有兴趣的可以去研读源码的具体实现过程。

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部