笔记1-3:动态代理
动态代理
特点:字节码随用随创建,随用随加载
作用:不修改源码的基础上对方法增强
分类:
基于接口的动态代理(缺点:如果被代理的类未实现任何接口则Proxy不能用)
基于子类的动态代理
基于接口的动态代理(代理实现接口的类)
涉及类:Proxy
提供:jdk官方
如何创建代理对象:使用Proxy类中的newProxyInstance方法
创建代理对象的要求:被代理类最少实现一个接口
newProxyInstance()参数:
ClassLoader:类加载器==用于加载代理对象字节码的。使用的是被代理对象的类加载器
Class[]:它是用于代理对象和被代理对象有相同的方法,即代理类实现的接口
InvvocationHandler对象:它是让我们写如何代理。我们一般都是写一个该接口的实现类。
通常情况下用匿名内部类,但不是必须的。此接口(InvvocationHandler)的实现类都是谁用谁写。
返回:一个被代理类类型的代理对象。
使用例子
//接口
public interface IProduce {
/**
* 销售
* @param money
*/
public void saleProduct(float money);
/**
* 售后
* @param money
*/
public void saleService(float money);
}
//实现类(厂家/被代理对象)
// 一个生产者
public class Produce implements IProduce{
public void saleProduct(float money){
//厂家发货,厂家获得销售商品的钱
System.out.println("销售产品,厂家拿到钱:"+money);
}
public void saleService(float money){
System.out.println("提供售后服务,厂家拿到钱:"+money);
}
}
//客户类(通过动态代理拿货)
/**
* 模拟一个消费者
* @author xiaoaiying
*/
public class Client {
@Test
public void test1(){
//获取厂家
final Produce produce = new Produce();
//直接联系厂家拿货
// produce.saleProduct(10000f);//结果:销售产品,厂家拿到钱:10000
//获取动态代理(代理商)
IProduce proxyProducer = (IProduce) Proxy.newProxyInstance(
produce.getClass().getClassLoader(),
produce.getClass().getInterfaces(),
new InvocationHandler() {
/**
* 作用:执行被代理对象的任何接口方法都会经过该方法,即相当于该方法具有拦截的功能
* @param proxy 代理对象的引用
* @param method 当前执行的方法
* @param args 当前执行方法所需的参数
* @return 和被代理对象执行的方法有相同的返回值
* @throws Throwable
*
* 注:匿名内部类访问外部成员要求成员必须是最终的即final修饰
* invoke()方法:执行当前方法
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
/**
* 可以在此提供增强的代码
*/
//创建返回值
Object returnValue = null;
//获取参数
Float money = (Float) args[0];
//判断当前方法是不是销售那个方法
if ("saleProduct".equals(method.getName())){
returnValue = method.invoke(produce,money*0.8f);//代理商从客户那里拿走了0.2的价钱
}
return returnValue;
}
});
//通过代理商拿货
proxyProducer.saleProduct(10000f);//结果:销售产品,厂家拿到钱:8000
}
}
基于子类的动态代理(代理普通类)
涉及类:Enhancer时
提供者:第三方cglib库
如何创建代理对象:使用Ehancer类中的create()方法
创建代理对象的要求:被代理类不能是最终类,即final修饰
create()参数:
Class:字节码==用于指定被代理对象的字节码
Callback:用于提供增强的代码
使用例子
//具体类
/**
* 一个生产者
*/
public class Produce{
/**
* 销售
* @param money
*/
public void saleProduct(float money){
//厂家发货,厂家获得销售商品的钱
System.out.println("销售产品,厂家拿到钱:"+money);
}
/**
* 售后
* @param money
*/
public void saleService(float money){
System.out.println("提供售后服务,厂家拿到钱:"+money);
}
}
//客户类(通过动态代理拿货)
public class Client {
final Produce produce = new Produce();
//基于子类动态代理
@Test
public void test1() {
//获取动态代理
Produce cglibProducer = (Produce) Enhancer.create(
produce.getClass(),
new MethodInterceptor() {
/**
* 被执行的代理对象的方法都会经过该方法
* @param proxy
* @param method
* @param args
* 以上三个参数与基于接口动态代理中invoke方法参数一样
* @param methodProxy
* @return
* @throws Throwable
*/
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
/**
* 可以在此提供增强的代码
*/
//创建返回值
Object returnValue = null;
//获取参数
Float money = (Float) args[0];
//判断当前方法是不是销售那个方法
if ("saleProduct".equals(method.getName())){
returnValue = method.invoke(produce,money*0.8f);//代理商从客户那里拿走了0.2的价钱
}
return returnValue;
}
});
//通过代理拿货
cglibProducer.saleProduct(12000f);//结果:销售产品,厂家拿到钱:9600
}
}