jdk代理与cglib代理

1. jdk静态代理

  jdk静态代理主要使用硬编码实现.他经过对在代理类中持有委托类的引用,来打到在委托类方法执行前和执行后进行处理,实现简单,容易理解.java

  代码以下:app

  1.业务逻辑接口框架

1 package jdkStaticProxy;
2 
3 public interface Service {
4 
5     public void doService();
6 
7 }

  2.业务逻辑实现类ide

1 package jdkStaticProxy;
2 
3 public class ServiceImpl implements Service {
4 
5     @Override
6     public void doService() {
7         System.out.println("this is doService method");
8     }
9 }

  3.代理类测试

 1 package jdkStaticProxy;
 2 
 3 public class ServiceProxy implements Service {
 4 
 5     private Service service;
 6 
 7     public ServiceProxy(Service service) {
 8         this.service = service;
 9     }
10 
11     @Override
12     public void doService() {
13         System.out.println("there is before method");//前置处理方法
14         service.doService();//业务逻辑方法
15         System.out.println("there is after method");//后置处理方法
16     }
17 }

  在代理类中持有一个委托类的应用,以达到在代理类中进行相关处理.this

  4.测试类编码

 1 package jdkStaticProxy;
 2 
 3 public class Main {
 4 
 5     public static void main(String[] args) {
 6         Service service=new ServiceImpl();
 7         Service serviceProxy=new ServiceProxy(service);
 8         serviceProxy.doService();
 9     }
10 
11 }

  以上就是jdk静态代理,很容易理解,可是他的问题也显而易见----dk静态代理由于是硬编码实现,因此可能会存在大量的重复代码.加入咱们的service有10个方法,那么咱们的代理类中就必须有10个对应的代理方法,这样的工做量是很是大.spa

2. jdk动态代理

  jdk动态代理主要使用反射实现.要使用jdk代理必须实现一个接口,缘由是jdk代理是用代理类替换委托类进行方法调用,为了让代理可以完成替换,就必须实现一个接口,这样jdk就能生成对应的代理类.代理类的生成主要经过一个Proxy工厂生成,代理类的方法经过调用一个InvocationHandler接口的invoke方法执行..net

  代码以下:代理

  1.业务逻辑接口

    同静态代理

  2.业务逻辑实现类

    同静态代理

  3.InvocationHandler

 1 package jdkDynamicProxy;
 2 
 3 import java.lang.reflect.InvocationHandler;
 4 import java.lang.reflect.Method;
 5 
 6 public class MyInvocationHandler implements InvocationHandler {
 7 
 8     private Object target;
 9 
1011 
12     public MyInvocationHandler(Object target) {
13         this.target = target;
14        15     }
16 
17     @Override
18     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
19 
20         System.out.println("there is before method");
21 
22         method.invoke(target,args);
23 
24         System.out.println("there is after method");
25 
26         return null;
27     }
28 
29 }

    从代码里面能够看出来,代理类持有委托类的引用.委托类的方法是经过反射来进行调用的.method是委托类的方法.

  4.测试类

package jdkDynamicProxy;

import java.lang.reflect.Proxy;

public class Main {

    public static void main(String[] args) {
        ServiceImpl service=new ServiceImpl();
        MyInvocationHandler myInvocationHandler=new MyInvocationHandler(service);

        Service service1= (Service) Proxy.newProxyInstance(
                service.getClass().getClassLoader(),//委托类的类加载器
                service.getClass().getInterfaces(),//委托类的接口
                myInvocationHandler);//InvocationHandler

        service1.doService();

        System.out.println("实际类型:"+service1.getClass());
    }
   
}

  Proxy是一个工厂类,调用newProxyInstance生成一个代理类,传入委托类加载器和委托类的接口是为了建立一个可以替换委托类的代理类(为何须要这两个参数请了解JVM如何判断两个类相等),InvocationHandler为代理类的逻辑方法.代码中的service1实际类型是com.sun.proxy.$Proxy0.代理类的建立是经过反射建立,有兴趣的读者能够研究Proxy的源码,也能够看这里

3. cglib动态代理

  cglib是一个开源库,他不须要委托类实现一个接口,他是经过建立一个继承委托类的代理类,来进行强化方法,代理类的实现方法经过调用MethodInterceptor的intercept方法.建立代理类主要借助asm这个java字节码生成框架.

  代码以下:

  1.业务逻辑类

    同静态代理

  2.intercept

 1 package cglibProxy;
 2 
 3 import net.sf.cglib.proxy.MethodInterceptor;
 4 import net.sf.cglib.proxy.MethodProxy;
 5 
 6 import java.lang.reflect.Method;
 7 
 8 public class MyInterceptor implements MethodInterceptor {
 9 
10     @Override
11     public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
12         System.out.println("-----before");
13         methodProxy.invokeSuper(o,objects);//调用父类(业务逻辑)方法
14         System.out.println("-----after");
15         return null;
16     }
17 
18 }

  其中method是委托类的方法,methodProxy是代理类的代理方法.

  3.测试方法

 1 package cglibProxy;
 2 
 3 import net.sf.cglib.proxy.Enhancer;
 4 
 5 public class Main {
 6 
 7     public static void main(String[] args) {
 8 
 9         Enhancer enhancer=new Enhancer();//该类是cglib的字节码生成器,可以直接生成对应代理类的字节码
10         enhancer.setSuperclass(Service.class);//继承委托类(final类不可被继承)
11         enhancer.setCallback(new MyInterceptor());//设置回调
12         Service service= (Service) enhancer.create();//生成代理对象
13 
14         service.doService();
15         System.out.println("实际类型:"+service.getClass());
16 
17     }
18 }

    代理类对象是由Enhancer类建立的。Enhancer是CGLIB的字节码加强器,能够很方便的对类进行拓展.经过设置回调方法和委托类,生成对应代理类的字节码,而后将代理类加载进来,生成代理对象.

    建立代理类的步骤以下:

      1.生成代理类的二进制字节码文件

      2.加载二进制字节码,生成Class对象( 例如使用Class.forName()方法 )

      3.经过反射机制得到实例构造,并建立代理类对象

    cglib原理请看这里

4. 各代理对比

  1.jdk静态代理:实现简单易懂,可是因为是硬编码实现,因此可能会出现大量重复代码.

  2.jdk动态代理:经过反射机制建立代理类以及代理类方法调用,他在建立代理类的效率上会比cglib高,可是在调用方法的效率上比cglib低.

  3.cglib动态代理:经过生成字节码的方式建立代理类,他在建立代理类的效率上因为要生成字节码以及加载类因此比jdk代理低,可是方法执行效率上因为是直接执行,不须要进行反射因此效率比jdk代理高.

相关文章
相关标签/搜索