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

JDK代理机制 学习总结

2016-06-18 17:34 369 查看
二、JDK代理机制

1、特点:

1)只能代理接口类。如果实现类中的方法需要增强,可以实现接口,重写接口里的方法即可。

2.)不需要引外界包,jdk  api自带API里有Proxy这个工具类。

2、使用

jdk代理类以一个demo的形式展示用法。

业务需要:通过代理类记录被代理对象中add方法的日志信息。

1)接口类  ProductDao

/**
*类说明:商品Dao接口<br/>
*创建日期:2016年6月18日<br/>
*
*/
public interface ProductDao {
public void addProduct();
public void updateProduct();
}

2)实现类  ProductDaoImpl
/**
*类说明:商品实现类<br/>
*创建日期:2016年6月18日<br/>
*
*/
public class ProductDaoImpl implements ProductDao{
@Override
public void addProduct() {
System.out.println("添加商品.....");
}
@Override
public void updateProduct() {
System.out.println("更新商品....");
}
}

3)代理类 ProductProxy
说明:上面的两个类里,ProductDao接口类是被代理对象,接下来这个类 ProductProxy是代理对象,代理  被代理对象 里的addProduct方法(这句话有点饶)。

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

public class ProductProxy implements InvocationHandler{
/**
* 第1步:引入被代理对象 ProductDao
*/
private ProductDao productDao;
public ProductProxy(ProductDao productDao){
this.productDao = productDao;
}

/**
* 第2步:通过Proxy类的实例化方法产生一个代理对象,并返回
* Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
* 参数解释
*/
public ProductDao createProductDao(){
return (ProductDao) Proxy.newProxyInstance(productDao.getClass().getClassLoader(), productDao
.getClass().getInterfaces(), this);
}

/**
* 第1.5步:代理对象拦截 被代理对象 中需要处理的方法,然后进行处理,这里是为add方法添加日志信息
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if(method.getName().equals("addProduct")){//拦截到指定的方法 addProduct()
System.out.println("这里是需要打印的日志信息......");
return method.invoke(productDao, args); //执行方法
}else{ //其他方法
return method.invoke(productDao, args); //执行方法
}
}

}
步骤:
第1步:引入被代理对象,这里是ProductDao;

第2步:产生一个代理对象并返回。

这里需要说明的是,我第一次学习这的时候就很烦恼,代理对象究竟是如何产生的呢?

  可以简单的理解为java自带一个工具类 Proxy ,这个类有个静态方法 newProxyInstance(xx,xx,xx),,我们只要知道调用这个方法,并且转换下类型就可以得到代理即可。

还有一点需要了解的就是这个方法里的三个参数:Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)* ClassLoader   loader : 类加载器,不理解的话直接记忆      productDao.getClass().getClassLoadeer()   ,这里的productDAO是被代理对象。
* Class<?>[]   interfaces : 类接口,前面说了jdk代理只能代理接口,这里代理的接口是ProductDao ,这里应写为: productDao.getClass().getInterfaces()。

* InvocationHandler   h : 这个类的作用体现在第1.5步里,首先我这里实现了这个接口,所以参数位置可以直接写this,代表invacationHandler的实现类。

其次为什么要写第1.5步呢,第2步的作用是产生一个代理对象并返回,但是如果什么操作都不做就返回就没有意思,第1.5不的作用就是截取需要处理的方法去处理。

第1.5步:在返回代理对象前执行的一个步骤,用来处理需要处理的方法。这个方法是实现InvovationHandler接口后重写的方法。

invoke()方法的三个参数简单介绍一个:proxy 代理对象,method 方法对象,args 参数

需要记忆的:

method.getName 是获得被代理对象的方法名,这里隐式的 遍历 了被代理对象里的所有方法。

method.invoke(productDao,args)  是执行被代理对象的原方法。究其本质,虽然会被add方法进行处理,但没有对原方法进行任何的改变。

4)测试结果

比较了使用代理和没有使用代理执行方法的结果,一目了然看出代理的作用:

public class TestJDKProxy {
public static void main(String[] args) {
//未使用代理对象执行方法
System.out.println("===========================未使用代理对象执行方法===============================");
ProductDao productDao = new ProductDaoImpl();
productDao.addProduct();
productDao.updateProduct();

//使用代理对象执行方法
System.out.println("==========================使用代理对象执行方法================================");
ProductDao productDao2 = new ProductDaoImpl();
ProductProxy productProxy = new ProductProxy(productDao2);
productDao2 = productProxy.createProductDao();
productDao2.addProduct();
productDao2.updateProduct();
}
}

控制台打印语句:
===========================未使用代理对象执行方法===============================

添加商品.....

更新商品....

==========================使用代理对象执行方法================================

这里是需要打印的日志信息......

添加商品.....

更新商品....
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  JDK 代理 接口