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();
}
}
控制台打印语句:
===========================未使用代理对象执行方法===============================
添加商品.....
更新商品....
==========================使用代理对象执行方法================================
这里是需要打印的日志信息......
添加商品.....
更新商品....
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动态代理VS CgLib
- fastjson处理接口时的一个问题
- Ubuntu 安装 JDK 问题
- 局域网与广域网接口标准
- RJ-45接口信号定义
- 依附品牌做代理 把握创业新机遇
- DVI 视频接口图文解析
- 代理区独立模式的说明
- 如何设置域名接口
- 通过C#实现自动售货机接口
- C#中IEnumerable接口用法实例分析
- C#中实现判断某个类是否实现了某个接口
- C#隐式/显示实现接口方法详解
- C#实现两接口中同名方法实例分析
- 详解C#中的接口属性以及属性访问器的访问限制
- C#中的ICustomFormatter及IFormatProvider接口用法揭秘
- C#接口实现方法实例分析
- http代理相关知识分析
- 基于C# 中可以new一个接口?的问题分析
- C#抽象类和接口的区别分析