了解代理模式,以及jdk的代理模式与cglib的代理模式的区别

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手写代理

   待完善

posted @ 2020-12-29 23:29  哇哇咔哇咔咔  阅读(228)  评论(0编辑  收藏  举报