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

初识jdk动态代理

2017-09-27 00:03 176 查看
在学习spring的时候有个重要的概念就是spring aop(面向切面编程),简单理解为纵向相同功能横向抽取,这里就用到了动态代理设计模式,只是用到了jdk的动态代理和cglib动态代理,因为使用jdk动态代理(优先使用)的话,被代理的对象必须要实现接口才能产生代理对象,如果没有接口,将不能实现动态代理技术。这时候会使用cglib代理,该技术可以对任何类生成代理,代理的原理是对目标对象进行继承代理。对象上使用了事务注解的时候,返回给我们的Service对象就是代理对象了,只是进行了增强(加了事务)。

简单理解可以认为动态代理可以产生原有对象的代理对象,但是对原有对象(方法)进行了增强。

举个简单的场景,店里卖衣服,经理可以直接卖给你,但是人多店大的话那么这个时候应该由店员或者秘书来与客户进行交易。比如经理卖件衣服给你是100,但是与店员交易也许就打折了,那么可以理解为对卖衣服的方法进行了增强。基于这个勉强的例子来写个jdk动态代理模板代码。

public interface ManagerService {
/**
* @param tradeNo 订单号
* @return 商品价格
*/
public int getPrice(String tradeNo);
}


public class ManagerServiceImpl implements ManagerService{

@Override
public int getPrice(String tradeNo) {
System.out.println("经理为您服务...");
return 999;
}

}


不使用动态代理时候进行测试

public class ManagerServiceTest {
public static void main(String[] args) {
ManagerService managerService = new ManagerServiceImpl();
int price = managerService.getPrice("15687");
System.out.println("订单号15687的商品价格为:"+price);
}
}


输出

经理为您服务...
订单号15687的商品价格为:999


这是经理直接进行交易,拿到原始价格为999

下面使用动态代理技术

public class ManagerServiceProxy {
/**
* 对接口方法getPrice进行代理
* @param discount 打折
* @param interfaceService 代理的接口
* @param implementService 接口的实现类
* @return
*/
@SuppressWarnings("unchecked")
public static<T> T getProxy(int discount,Class interfaceService,Class implementService){
return (T)Proxy.newProxyInstance(interfaceService.getClassLoader(),
new Class[]{interfaceService}, new InvocationHandler() {

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//创建实现类的Class实例对象
Object obj = implementService.newInstance();
//传入参数,调用方法获得返回值
int originalPrice = (int)method.invoke(obj, args);
//打折后价格
int discountPrice = originalPrice-discount;
System.out.println("经理休息,秘书为您服务...");
return discountPrice;
}
});
}
}


对代理对象进行测试

public class ProxyTest {
public static void main(String[] args) {
//获得代理对象
ManagerService proxy = ManagerServiceProxy.getProxy(339, ManagerService.class, ManagerServiceImpl.class);
//执行加强的方法
int price = proxy.getPrice("15687");
System.out.println("订单号15687的商品价格为:"+price);
}
}


输出:

经理为您服务...
经理休息,秘书为您服务...
订单号15687的商品价格为:660
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: