1.代理模式
代理模式属于设计模式中的结构性设计模式。主要有两个目的,一是保护目标对象不受更改,二是增强目标对象的功能
实现方式是代理真正需要执行的对象方法,在真正的方法执行前或者执行后,可以做一些自定义的操作。官方一点的解释就是为其他对象提供代理,以控制这个对象的访问。
使用场景为:当你需要对这个类做修改的时候,但是又不想修改这个类的时候,就可以通过代理的方式实现。
2.jdk的代理实现
拿吃饭举例,人类吃饭吃前要洗手,吃后要洗碗
Eat:
1 public interface Eat { 2 3 void eatRice(); 4 }
JdkEat:
1 public class JDKEat implements Eat { 2 3 @Override 4 public void eatRice() { 5 System.out.println("吃饭饭"); 6 } 7 }
JDKPeopleEat:
1 public class JDKPeopleEat implements InvocationHandler { //JDK使用代理需要实现InvocationHandler接口 2 3 private Eat target; 4 //通过注入拿到需要代理的类,然后去创建代理对象返回 5 public Object getInstance(Eat eat){ 6 this.target = eat; 7 Class<? extends Eat> aClass = target.getClass(); 8 return Proxy.newProxyInstance(aClass.getClassLoader(),aClass.getInterfaces(),this); 9 } 10 //重写InvokeHandler的invoke方法,来调用实际上执行的内容,自己需要增强的部分也是在这里 11 @Override 12 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 13 before(); 14 Object invoke = method.invoke(this.target, args); 15 after(); 16 return invoke; 17 } 18 19 private void before(){ 20 System.out.println("洗手手"); 21 } 22 23 private void after(){ 24 System.out.println("洗碗碗"); 25 } 26 27 }
JDKProxyTest:
1 public class JDKProxyTest { 2 public static void main(String[] args) { 3 Eat instance = (Eat)new JDKPeopleEat().getInstance(new JDKEat()); 4 instance.eatRice(); 5 } 6 }
3.cglib的代理实现
CGLibEat:
1 public class CGLibEat { 2 3 public void eatRice(){ 4 System.out.println("吃饭饭"); 5 } 6 }
CGLibPeopleEat:
1 public class CGLibPeopleEat implements MethodInterceptor { 2 3 public Object getInstance(Class<?> clazz){ 4 //相当于Proxy,代理的工具类 5 Enhancer enhancer = new Enhancer(); 6 enhancer.setSuperclass(clazz); 7 enhancer.setCallback(this); 8 return enhancer.create(); 9 } 10 11 @Override 12 public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { 13 before(); 14 Object obj = methodProxy.invokeSuper(o,objects); 15 after(); 16 return obj; 17 } 18 19 private void before(){ 20 System.out.println("洗手手"); 21 } 22 23 private void after(){ 24 System.out.println("刷碗碗"); 25 } 26 }
CGLibTest:
1 public class CGLibTest { 2 public static void main(String[] args) { 3 4 //JDK是采用读取接口的信息 5 //CGLib覆盖父类方法 6 //目的:都是生成一个新的类,去实现增强代码逻辑的功能 7 8 //JDK Proxy 对于用户而言,必须要有一个接口实现,目标类相对来说复杂 9 //CGLib 可以代理任意一个普通的类,没有任何要求 10 11 //CGLib 生成代理逻辑更复杂,效率,调用效率更高,生成一个包含了所有的逻辑的FastClass,不再需要反射调用 12 //JDK Proxy生成代理的逻辑简单,执行效率相对要低,每次都要反射动态调用 13 14 //CGLib 有个坑,CGLib不能代理final的方法 15 CGLibEat obj = (CGLibEat) new CGLibPeopleEat().getInstance(CGLibEat.class); 16 obj.eatRice(); 17 18 } 19 }
4.仿照jdk手写代理
待完善