Java dynamic proxy -CGLIB (3)

Disclaimer: This article is a blogger original article, shall not be reproduced without the bloggers allowed. https://blog.csdn.net/zhangyong01245/article/details/90644933

CGLIB dynamic proxy:

  1. JDK dynamic proxy, JDK dynamic proxy class must implement an interface, and the generated proxy class is the interface implementation class, i.e. the class of agents sibling classes implemented inside the JDK,
  2. cglib agent class, without being forced to implement an interface that generates a proxy class is a subclass of the class of the proxy, and the proxy class methods are overridden, but also the introduction of additional Jar

Simple implementation:

  1. Calculate the total time a sql call

Code logic:

  1. Introducing Maven configuration:
<dependency>
      <groupId>cglib</groupId>
      <artifactId>cglib</artifactId>
      <version>3.2.12</version>
</dependency>
  1. Create a class that needs to be SqlService agent:
public class SqlService {
    public void executeSql1() throws InterruptedException {
        System.out.println("Sql 开始执行.....");
        Thread.sleep(1000);
        System.out.println("Sql 执行结束.....");
    }
}
  1. Create a proxy class: SqlFacadeCglib
public class SqlFacadeCglib implements MethodInterceptor {

    /**
     * 被代理的对象
     */
    private Object target;

    public SqlFacadeCglib(Object target) {
        this.target = target;
    }

    /**
     *  实现回调方法
     * @param obj 代理的对象
     * @param method 被代理对象的方法
     * @param args  参数集合
     * @param proxy 生成的代理类的方法
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        // 开始执行时间
        Long startTime = System.currentTimeMillis();
        // //调用业务类(父类中)的方法
        Object result = proxy.invokeSuper(obj, args);
        // 执行结束
        Long endTime = System.currentTimeMillis();
        System.out.println(target.getClass().getName()+"执行executeSql耗时"+(endTime-startTime)+"ms");
        return result;
    }
}
  1. Create a Test:
public class Test {

    public static void main(String[] args) throws InterruptedException, IOException {
        // 将class 文件保存
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "F:/mycode/Git/spring-mvc/learn/design-pattern-learn/src/main/java/com/lot/cglibproxy");
        SqlService sqlService = new SqlService();
        SqlFacadeCglib sqlFacadeCglib = new SqlFacadeCglib(sqlService);

        //创建加强器,用来创建动态代理类
        Enhancer enhancer = new Enhancer();
        //为加强器指定要代理的业务类(即:为下面生成的代理类指定父类)
        enhancer.setSuperclass(sqlService.getClass());

        //设置回调:对于代理类上所有方法的调用,都会调用CallBack,而Callback则需要实现intercept()方法进行拦
        enhancer.setCallback(sqlFacadeCglib);
        // 创建动态代理类对象并返回
        SqlService sqlServiceProxy = (SqlService)enhancer.create();
        // 调用
        sqlServiceProxy.executeSql1();

    }
}

Results of the:

  1. Print Console:
CGLIB debugging enabled, writing to 'F:/mycode/Git/spring-mvc/learn/design-pattern-learn/src/main/java/com/lot/cglibproxy'
Sql 开始执行.....
Sql 执行结束.....
com.lot.cglibproxy.SqlService执行executeSql耗时1018ms
  1. Debug sqlServiceProxy see definition at:
    Here Insert Picture Description
  2. The binding Debug display System.setProperty () written to the file's location, we find the generated proxy class: SqlService ¥¥ EnhancerByCGLIB ¥¥ ecb184ce: (after brief code):
public class SqlService$$EnhancerByCGLIB$$ecb184ce extends SqlService implements Factory {

    static void CGLIB$STATICHOOK1() {
        CGLIB$THREAD_CALLBACKS = new ThreadLocal();
        // 参数集合
        CGLIB$emptyArgs = new Object[0];
        Class var0 = Class.forName("com.lot.cglibproxy.SqlService$$EnhancerByCGLIB$$ecb184ce");
        Class var1;
        Method[] var10000 = ReflectUtils.findMethods(new String[]{"equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;"}, (var1 = Class.forName("java.lang.Object")).getDeclaredMethods());
        CGLIB$equals$1$Method = var10000[0];
        CGLIB$equals$1$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$1");
        CGLIB$toString$2$Method = var10000[1];
        CGLIB$toString$2$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$2");
        CGLIB$hashCode$3$Method = var10000[2];
        CGLIB$hashCode$3$Proxy = MethodProxy.create(var1, var0, "()I", "hashCode", "CGLIB$hashCode$3");
        CGLIB$clone$4$Method = var10000[3];
        CGLIB$clone$4$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$4");
        // 被代理类的 executeSql1() 方法
        CGLIB$executeSql1$0$Method = ReflectUtils.findMethods(new String[]{"executeSql1", "()V"}, (var1 = Class.forName("com.lot.cglibproxy.SqlService")).getDeclaredMethods())[0];
        // 生成代理类的 executeSql1() 方法
        CGLIB$executeSql1$0$Proxy = MethodProxy.create(var1, var0, "()V", "executeSql1", "CGLIB$executeSql1$0");
    }
    public final void executeSql1() throws InterruptedException {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (this.CGLIB$CALLBACK_0 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        if (var10000 != null) {
            // 执行 SqlFacadeCglib.intercept() 方法
            var10000.intercept(this, CGLIB$executeSql1$0$Method, CGLIB$emptyArgs, CGLIB$executeSql1$0$Proxy);
        } else {
            super.executeSql1();
        }
    }
    // 省略代码,有兴趣大家可以查看
}

to sum up:

  1. In Test.main () method, and the class SqlService Enhancer strengthen our own definition, SqlFacadeCglib combination, and then by enhancer.create () to create a proxy class. From source proxy class, we can see that in fact a proxy class is a subclass of our business class
  2. executeSql1 When we execute sqlServiceProxy.executeSql1 () actually access CGLIB generated proxy class () method, then calling SqlFacadeCglib.intercept () to do some public logic processing, which proxy.invokeSuper (obj, args) this code to perform the method of our business logic class: SqlService.executeSql1 ()
  3. In fact, the dynamic proxy purpose is to help us integrate business logic classes, and a total approach and generate proxy classes, which greatly simplifies our development effort, which has a deep Spring in the use of dynamic proxies.

Follow-up:

1, the static agent: https://blog.csdn.net/zhangyong01245/article/details/90519769
2, the Java dynamic proxy implementation: https://blog.csdn.net/zhangyong01245/article/details/90598309
3, dynamic CGLIB Acting and logic: https://blog.csdn.net/zhangyong01245/article/details/90644933

These are the bloggers own understanding and ideas, please leave a message if any objections, bloggers will be the first time to resolve

Guess you like

Origin blog.csdn.net/zhangyong01245/article/details/90644933