代理模式是指为其他对象提供一种代理,以控制对这个对象的访问。代理对象在客户端和目标对象之间起到中介作用。
根据被代理对象的类型,代理模式分为静态代理和动态代理。静态代理只可以代理指定类型,动态代理不限制类型。
定义接口 Person
public interface Person {
void findHouse();
}
被代理对象 Renter
public class Renter implements Person {
@Override
public void findHouse() {
System.out.println("三室两厅");
System.out.println("交通方便");
}
}
代理对象 AgencyStaticProxy,增强部位 doBefore(),doAfter()
public class AgencyStaticProxy {
private Person person;
public AgencyStaticProxy(Person person) {
this.person = person;
}
public void findHouse() {
doBefore();
person.findHouse();
doAfter();
}
void doBefore() {
System.out.println("请描述房子需求:静态代理");
}
void doAfter() {
System.out.println("已成交,请支付中介费用2000元");
}
}
测试类
public class Test {
public static void main(String[] args) {
AgencyStaticProxy agency = new AgencyStaticProxy(new Renter());
agency.findHouse();
}
}
代理对象 AgencyJdkProxy ,实现InvocationHandler 接口
public class AgencyJdkProxy implements InvocationHandler {
private Object object;
public Object getInstance(Object target) {
this.object = target;
Class> clazz = object.getClass();
Object o = Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
return o;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
doBefore();
Object invoke = method.invoke(this.object, args);
doAfter();
return invoke;
}
void doBefore() {
System.out.println("请描述房子需求:JDK动态代理");
}
void doAfter() {
System.out.println("已成交,请支付中介费用2000元");
}
}
测试类
public class Test {
public static void main(String[] args) {
Renter renter = new Renter();
Person person = (Person) new AgencyJdkProxy().getInstance(renter);
person.findHouse();
}
}
JDK动态代理的被代理对象必须实现 接口。
被代理对象 RenterOnly
public class RenterOnly {
public void findHouse() {
System.out.println("三室两厅");
System.out.println("交通方便");
}
}
代理对象AgencyCglibProxy
public class AgencyCglibProxy implements MethodInterceptor {
public Object getInstance(Class> clazz) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
doBefore();
Object invokeSuper = methodProxy.invokeSuper(o, objects);
doAfter();
return invokeSuper ;
}
void doBefore() {
System.out.println("请描述房子需求:Cglib动态代理");
}
void doAfter() {
System.out.println("已成交,请支付中介费用2000元");
}
}
测试类
public class Test {
public static void main(String[] args) {
RenterOnly renterOnly = (RenterOnly)new AgencyCglibProxy().getInstance(RenterOnly.class);
renterOnly.findHouse();
}
}
1、JDK动态代理是实现了被代理对象的接口,Cglib是继承了被代理对象。
2、JDK动态代理和Cglib动态代理都是在运行期生成字节码,JDK是直接写Class字节码,Cglib使用ASM框架写Class字节码,Cglib代理实现更复杂,生成代理类比JDK效率低。
3、JDK调用代理方法,是通过反射机制调用,Cglib是通过FastClass机制直接调用方法,Cglib执行效率更高。
4、Cglib无法代理 final修饰的方法