基于接口的动态代理
提供者:JDK 官方的 Proxy 类。
要求:被代理类最少实现一个接口。
被代理类
public class Product implements IProduct {
public void sell(double money){
System.out.println("电脑卖了"+money);
}
}
接口
public interface IProduct {
public void sell(double money);
}
package Proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyProduct {
public static void main(String[] args) {
final Product product = new Product();
/**
* 代理:
* 间接。
* 获取代理对象:
* 要求:
* 被代理类最少实现一个接口
* 创建的方式
* Proxy.newProxyInstance(三个参数)
* 参数含义:
* ClassLoader:和被代理对象使用相同的类加载器。
* Interfaces:和被代理对象具有相同的行为。实现相同的接口。
* InvocationHandler:如何代理。
*
*/
IProduct ProxyProduct = (IProduct) Proxy.newProxyInstance(ProxyProduct.class.getClassLoader(), Product.class.getInterfaces(), new InvocationHandler() {
/**
* 执行被代理对象的任何方法,都会经过该方法。
* 此方法有拦截的功能。
*
* 参数:
* proxy:代理对象的引用。不一定每次都用得到
* method:当前执行的方法对象
* args:执行方法所需的参数
* 返回值:
* 当前执行方法的返回值
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
double money = (double) args[0];
if (method.getName().equals("sell")) {
return method.invoke(product, money * 0.8);
}
return null;
}
});
ProxyProduct.sell(1000);
}
}
基于子类的动态代理
提供者:第三方的 CGLib,如果报 asmxxxx 异常,需要导入 asm.jar。
要求:被代理类不能用 final 修饰的类(最终类)。
public class Product {
public void sell(double money){
System.out.println("电脑卖了"+money);
}
}
package cglib;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class ProxyProduct {
public static void main(String[] args) {
final Product product = new Product();
/**
* 基于子类的动态代理
* 要求:
* 被代理对象不能是最终类
* 用到的类:
* Enhancer
* 用到的方法:
* create(Class, Callback)
* 方法的参数:
* Class:被代理对象的字节码
* Callback:如何代理
**/
Product proxyProduct = (Product) Enhancer.create(Product.class, new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
double money = (double) args[0];
if (method.getName().equals("sell")) {
return method.invoke(product, money * 0.8);
}
return null;
}
});
proxyProduct.sell(8000);
}
}