代理模式是一种设计模式,提供了对目标对象额外的访问方式,即通过代理对象访问目标对象,这样可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对象的功能。
代理模式又分为:静态代理、jdk动态代理、cglib动态代理。由于静态代理会产生过多的代理类,一旦接口增加方法,目标对象与代理对象都要进行修改,不易维护。而动态代理是动态地在内存中构建代理对象,从而实现对目标对象的代理功能,接口增加方法时代理对象不受影响 。下面我们讲讲jdk动态代理和cglib动态代理实现及区别
jdk动态代理实现
@Test
public void test(){
//目标对象
Person target = new Intermediary("中介1号", new Tenant("李四"));
//InvocationHandler
InvocationHandler handler = new RentInvocationHandler(target);
//获取代理对象
Person proxyInstance = (Person) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), handler);
//通过代理对象调用
proxyInstance.rentHouse();
}
// 代理对象
public class RentInvocationHandler implements InvocationHandler {
/**
* 被代理的目标对象
*/
private Object target;
public RentInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("租房前预处理工作...");
Object returnValue = method.invoke(target, args);
System.out.println("租房后善后工作...");
return returnValue;
}
}
// 目标对象接口
public interface Person {
/**
* 租房
*/
void rentHouse();
}
public class Intermediary implements Person {
private String name;
/**
* 租房者
*/
private Person tenant;
public Intermediary(String name, Person tenant) {
this.name = name;
this.tenant = tenant;
}
@Override
public void rentHouse() {
System.out.println("中介 " + this.name + "确定租房预算,带领查看房源...");
tenant.rentHouse();
System.out.println("中介 " + this.name + "带领客户租房完成,合同签订完成,收取佣金,准备跑路...");
}
}
public class Tenant implements Person {
private String name;
public Tenant(String name) {
this.name = name;
}
@Override
public void rentHouse() {
System.out.println(this.name + " 正在租房中...");
}
}
cglib动态代理
@Test
public void test(){
//目标对象
Runner runner = new Runner("李四");
//代理对象
RunnerMethodInterceptor interceptor = new RunnerMethodInterceptor(runner);
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(runner.getClass());
//设置回调
enhancer.setCallback(interceptor);
Runner proxyInstance = (Runner) enhancer.create();
proxyInstance.run();
}
// 代理对象
public class RunnerMethodInterceptor implements MethodInterceptor {
/**
* 目标对象
*/
private Object target;
public RunnerMethodInterceptor(Object target) {
this.target = target;
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("踢两脚 加速...");
Object returnVal = method.invoke(target, objects);
System.out.println("拽两下 减速...");
return returnVal;
}
}
public class Runner {
private String name;
public Runner() {
}
public Runner(String name) {
this.name = name;
}
public void run() {
System.out.println(this.name + " 跑的飞快...");
}
}
区别
1.JDK动态代理是实现了被代理对象的接口,Cglib是继承了被代理对象。
2.JDK和Cglib都是在运行期生成字节码,JDK是直接写Class字节码,Cglib使用ASM框架写Class字节码,Cglib代理实现更复杂,生成代理类比JDK效率低。
3.JDK调用代理方法,是通过反射机制调用,Cglib是通过FastClass机制直接调用方法,Cglib执行效率更高。