代理模式 代理模式是对对象的功能增强。比如前置通知和后置通知。
代理模式分为两种,静态代理,动态代理;动态代理又分为jdk代理和cglib代理。
静态代理 通常被代理对象实现同一个接口,代理对象通过接口动态构造了被代理对象,并且把被代理对象的接口方法做逐一的增强。
1 2 3 4 5 6 public interface Car { void drive(); void stop(); }
1 2 3 4 5 6 7 8 9 10 11 12 public class Benz implements Car { @Override public void drive() { System.out.println("Benz car drive"); } @Override public void stop() { System.out.println("Benz car stop"); } }
1 2 3 4 5 6 7 8 9 10 11 12 public class Baoma implements Car { @Override public void drive() { System.out.println("Baoma Car drive"); } @Override public void stop() { System.out.println("Baoma car stop"); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 public class Driver { private Car car; public Driver(Car car){ this.car = car; } public void drive(){ before(); car.drive(); after(); } public void stop(){ before(); car.stop(); after(); } public void before(){ System.out.println("**************"); } public void after(){ System.out.println("--------------"); } }
1 2 3 4 5 6 7 public class Test { public static void main(String[] args) { Driver driver = new Driver(new Baoma()); driver.drive(); driver.stop(); } }
动态代理 动态代理分两种,jdk和cglib
jdk代理 jdk是jdk自带的代理,不需要任何依赖,对象需要实现同一个接口,代理对象需要实现InvocationHandler,依赖倒置原则,减少对代理类的依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public class JdkDriver implements InvocationHandler { private Car car; @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { before(); Object result = method.invoke(this.car,args); after(); return result; } public Car getInstance(Car car){ this.car = car; Class<?> clazz = car.getClass(); return (Car)Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),this); } public void before(){ System.out.println("****************"); } public void after(){ System.out.println("-----------------"); } }
1 2 3 4 5 6 7 8 public class Test { public static void main(String[] args) { JdkDriver jdkDriver = new JdkDriver(); Car car = jdkDriver.getInstance(new Baoma()); car.drive(); car.speed(); } }
反射代理类,实现InvocationHandler,实现ivoke方法,对类方法进行修饰;提供get方法,return jdk的proxy类的代理生成对象,需要classloader,interfaces,this;
反射原理:动态生成源代码->输出到磁盘->编译成.class文件->加载到jvm中使用
Cglib代理 不需要实现特定的接口,cglib代理类实现MethodInterceptor,提供intercept和get方法
1 2 3 4 5 public class Car { public void buy(){ System.out.println("i want to buy a car"); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public class Mycglibproxy implements MethodInterceptor { @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { before(); Object obj = methodProxy.invokeSuper(o,objects); after(); return obj; } public Object getInstance(Class<?> clazz){ Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(clazz); enhancer.setCallback(this); return enhancer.create(); } public void before(){ System.out.println("****************"); } public void after(){ System.out.println("-----------------"); } }
1 2 3 4 5 6 public class Test { public static void main(String[] args) { Car car = (Car) new Mycglibproxy().getInstance(Car.class); car.buy(); } }
区别 1.jdk代理基于反射,cglib使用的是asm框架,fastclass机制
2.jdk一定要有接口,cglib不能实现final类