动态代理
动态代理:
1,特点:字节码随用随创建,随用随加载
2,作用:不修改源码的基础上对方法增强
3,分类:
(1)基于接口的动态代理
(2)基于子类的动态代理
(1)基于接口的动态代理:
涉及的类:Proxy
提供者:JDK官方
如何创建代理对象:使用Proxy类中的newProxyInstance方法
创建代理对象的要求:被代理类最少实现一个接口,当producer不实现任何接口的时候,代理对象是无法使用的
newProxyInstance方法的三个参数:
(1)ClassLoader:类加载器,它是用于加载代理对象字节码的。和被代理对象使用相同的类加载器。代理谁的就用谁的 .getClass().getClassLoader() 固定写法。
(2)Class[]:字节码数组,它是用于让代理对象和被代理对象有相同方法。固定写法。
(3)InvocationHandler:一个接口 用于提供增强的代码,它是让我们写如何代理。我们一般都是写一个该接口的实现类,通常情况下都是匿名内部类,但不是必须的。此接口的实现类都是谁用谁写。
被代理的对象 Produer
package x.xss.proxy;
//一个生产者
public class Producer implements IProducer{
/**
* 销售产品
* @param money
*/
public void saleProduct(float money){
System.out.println("销售产品,并拿到钱:"+money);
}
/**
* 售后
* @param money
*/
public void afterService(float money){
System.out.println("提供售后服务,并拿到钱:"+money);
}
}
被代理类,实现的接口
package x.xss.proxy;
//对生产厂家要求的接口
public interface IProducer {
/**
* 销售产品
* @param money
*/
public void saleProduct(float money);
/**
* 售后
* @param money
*/
public void afterService(float money);
}
消费者去找代理对象消费
//一个消费者
public class Client {
public static void main(String[] args) {
final Producer producer= new Producer(); // 匿名内部类方法访问外部成员变量时,外部成员变量要求是最终的
IProducer proxyProducer = (IProducer)Proxy.newProxyInstance(
producer.getClass().getClassLoader(),
producer.getClass().getInterfaces(),
new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
/**
* 提供增强的代码
*/
Object returnValue = null;
//1,提供方法执行的参数
Float money = (Float)args[0];
//2,判断当前方法是不是销售
if("saleProduct".equals(method.getName())){
returnValue = method.invoke(producer, money*0.8f);
}
return returnValue;
}
});
proxyProducer.saleProduct(10000f);//消费者消费 ,给代理对象付了一万元
}
}
(2) 基于子类的动态代理:
涉及的类:Enhancer
提供者:第三方cglib库 需导入cglib 的依赖 asm
如何创建代理对象:使用Enhancer类中的create方法
创建代理对象的要求:被代理类不能是最终类
create方法的三个参数:
Class:字节码,它是用于指定被代理对象的字节码
Callback:用于提供增强的代码,
它是让我们写如何代理。我们一般都是写一个该接口的实现类,
通常情况下都是匿名内部类,但不是必须的。
此接口的实现类都是谁用谁写。
我们一般写的都是该接口的子接口实现类: MethodInterceptor
被代理的对象
package x.xss.proxy;
//一个生产者
public class Producer implements IProducer{
/**
* 销售产品
* @param money
*/
public void saleProduct(float money){
System.out.println("销售产品,并拿到钱:"+money);
}
/**
* 售后
* @param money
*/
public void afterService(float money){
System.out.println("提供售后服务,并拿到钱:"+money);
}
}
消费者去找代理对象消费
public class Client {
public static void main(String[] args) {
final Producer producer = new Producer();
Producer cglibProducer =(Producer) Enhancer.create(producer.getClass(),new MethodInterceptor(){
/**
* 执行被代理对象的任何方法都会经过该方法
* @param proxy
* @param method
* @param args
* 以上三个参数和基于接口的动态代理中 invoke 方法的参数是一样的
* @param methodProxy :当前执行方法的代理对象
* @return
* @throws Throwable
*/
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy)throws Throwable{
//提供增强的代码
Object returnValue = null;
//1,提供方法执行的参数
Float money = (Float)args[0];
//2,判断当前方法是不是销售
if("saleProduct".equals(method.getName())){
returnValue = method.invoke(producer, money*0.8f);
}
return returnValue;
}
});
cglibProducer.saleProduct(12000f);
}
}