代理模式
静态代理
1、代理类与被代理类实现同一个接口
2、代理类持有被代理类的引用
3、使用代理对象调用方法时,在代理对象执行方法前后进行增强
顶层接口
public interface Student {
void doingHomework();
}
被代理类
public class ZhanSan implements Student {
@Override
public void doingHomework() {
System.out.println("张三的作业");
}
}
代理类
public class ProxyStudent implements Student {
private Student student;
ProxyStudent(Student student){
this.student = student;
}
private void before(){
System.out.println("开始帮忙写作业");
}
private void after(){
System.out.println("结束帮忙写作业");
}
@Override
public void doingHomework() {
before();
student.doingHomework();
after();
}
}
测试
public static void main(String[] args) {
ProxyStudent proxyStudent = new ProxyStudent(new ZhanSan());
proxyStudent.doingHomework();
}
特点:
- 需要新增方法时,需要改动代理类与被代理类的代码
- 实现简单
- 执行速度快
动态代理
cglib
public class CglibProxy implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("before1");
Object result = methodProxy.invokeSuper(o, objects);
System.out.println("after1");
return result;
}
public static void main(String[] args) {
CglibProxy cglibProxy = new CglibProxy();
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(ZhanSan.class);
enhancer.setCallback(cglibProxy);
Student o = (Student)enhancer.create();
o.doingHomework();
}
}
jdk
public class ObjectProxy implements InvocationHandler {
private ZhanSan zhanSan;
public ObjectProxy(ZhanSan zhanSan){
this.zhanSan = zhanSan;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before");
Object result = method.invoke(this.zhanSan, args);
System.out.println("after");
return result;
}
public static void main(String[] args) {
ZhanSan zhanSan = new ZhanSan();
ObjectProxy objectProxy = new ObjectProxy(zhanSan);
Class aClass = zhanSan.getClass();
Student o = (Student)Proxy.newProxyInstance(aClass.getClassLoader(), aClass.getInterfaces(), objectProxy);
o.doingHomework();
}
}
cglib与jdk的区别
cglib
- 继承了被代理对象
- 使用ASM框架写class字节码,生成对个对象生成速度慢
- 通过FastClass机制通过index快速定位到方法直接调用,执行效率更快
- 无法代理被final修饰的类(final修饰的类无法被继承)
- private修饰的方法无法被代理
jdk
- 实现了被代理对象的接口
- 直接写class字节码,生成速度快
- 通过反射调用代理方法,执行效率慢