欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

SAP ABAP CGLIB(Code Generation Library)的模拟实现 ABAPSAPSAP云平台SAP Cloud PlatformCloud 

程序员文章站 2022-05-30 07:57:24
...

What is CGLIB?

A Byte Code Generation Library which is high level API to generate and transform Java byte code. It is used in various scenarios such as AOP, testing, data access frameworks to generate dynamic proxy objects and intercept field access.

See one example in unit test.

In line 17, a new dynamic proxy class is generated as mock. In line 19, we tell the proxy, “if get(0) is called on this mock class, then return mocked data “hello, world”. As a result, in line 23 “result: hello, world” will be printed out.

 

SAP ABAP CGLIB(Code Generation Library)的模拟实现
            
    
    
        ABAPSAPSAP云平台SAP Cloud PlatformCloud 

 

In debugger you can find that the variable in line 17 is mocked by CGLIB:

 

SAP ABAP CGLIB(Code Generation Library)的模拟实现
            
    
    
        ABAPSAPSAP云平台SAP Cloud PlatformCloud 

 

Its byte code is generated dynamically and stored in variable byte[] b in line 217.

 

SAP ABAP CGLIB(Code Generation Library)的模拟实现
            
    
    
        ABAPSAPSAP云平台SAP Cloud PlatformCloud 

 

Let’s see another example of injecting pre-exit and post-exit ( which ABAPers are very familiar with ) into a given method via dynamic proxy generated by CGLIB:

(1) I have a class MyMEthodExitDemo which has a normal method myFun. (2) A new dynamic proxy class is generated in method createProxy which has a method with equal name as original class plus custom enhancement covered by class JerryEnhancement.

 

SAP ABAP CGLIB(Code Generation Library)的模拟实现
            
    
    
        ABAPSAPSAP云平台SAP Cloud PlatformCloud 

 

(3) The pre-exit and post-exit are defined in class JerryEnhancement which implements interface MethodInterceptor defined in CGLIB library. The original method is generated in line 14, with pre-exit before it ( line 13 ) and post-exit after it ( line 15 ).

 

SAP ABAP CGLIB(Code Generation Library)的模拟实现
            
    
    
        ABAPSAPSAP云平台SAP Cloud PlatformCloud 

 

Execute result:

 

SAP ABAP CGLIB(Code Generation Library)的模拟实现
            
    
    
        ABAPSAPSAP云平台SAP Cloud PlatformCloud 

 

How does this example work under the hood?

I implement a demo in ABAP with the same logic.

(1) I have a very simple ABAP class with only one public method which will print “Hello World”:

 

SAP ABAP CGLIB(Code Generation Library)的模拟实现
            
    
    
        ABAPSAPSAP云平台SAP Cloud PlatformCloud 

 

(2) The CGLIB utility class in line 5 simulates the logic in Java, which will construct a proxy class based on existing global class ZCL_JAVA_CGLIB. The generated proxy class will be DYNAMICALLY injected with two enhancement implemented by zcl_jerry_preexit and zcl_jerry_postexit.

 

SAP ABAP CGLIB(Code Generation Library)的模拟实现
            
    
    
        ABAPSAPSAP云平台SAP Cloud PlatformCloud 

 

There are two interfaces defined for pre-exit and post-exit logics which contain only one EXECUTE method without any parameters:

 

SAP ABAP CGLIB(Code Generation Library)的模拟实现
            
    
    
        ABAPSAPSAP云平台SAP Cloud PlatformCloud SAP ABAP CGLIB(Code Generation Library)的模拟实现
            
    
    
        ABAPSAPSAP云平台SAP Cloud PlatformCloud 

 

And zcl_jerry_preexit and zcl_jerry_postexit implement these two interfaces accordingly:

 

SAP ABAP CGLIB(Code Generation Library)的模拟实现
            
    
    
        ABAPSAPSAP云平台SAP Cloud PlatformCloud SAP ABAP CGLIB(Code Generation Library)的模拟实现
            
    
    
        ABAPSAPSAP云平台SAP Cloud PlatformCloud 

 

once method greet in line 16 is called, the enhanced version of method greet is called:

 

SAP ABAP CGLIB(Code Generation Library)的模拟实现
            
    
    
        ABAPSAPSAP云平台SAP Cloud PlatformCloud 

 

By this way, the method greet is enhanced in a non-invasive approach – no modification on original class, no new class are persisted in repository.

The method get_proxy of zcl_abap_cglib_tool does the magic, I just follow the idea of CGLIB implementation in Java:

 

SAP ABAP CGLIB(Code Generation Library)的模拟实现
            
    
    
        ABAPSAPSAP云平台SAP Cloud PlatformCloud 

 

The pre-exit and post-exit passed by consumer are dynamically injected into proxy class here:

 

SAP ABAP CGLIB(Code Generation Library)的模拟实现
            
    
    
        ABAPSAPSAP云平台SAP Cloud PlatformCloud 

 

Till now you should be familiar with CGLIB idea, and it is quite easy to understand why it is NOT possible to create a proxy class based on a final class by CGLIB, simply because a final class could not be subclassed.

The report to consume it:

REPORT zcglib_proxy_generate.

DATA: lo_proxy TYPE REF TO object.

CALL METHOD zcl_abap_cglib_tool=>get_proxy
  EXPORTING
    iv_class_name = 'ZCL_JAVA_CGLIB'
    io_pre_exit   = NEW zcl_jerry_preexit( )
    io_post_exit  = NEW zcl_jerry_postexit( )
  RECEIVING
    ro_proxy      = lo_proxy.

CHECK lo_proxy IS NOT INITIAL.

DATA(lo_class) = CAST zcl_java_cglib( lo_proxy ).
lo_class->greet( ).

Update on 2017-02-02 CGLIB use scenario

The CGLIB is widely used in many Java framework, for example Mockito as a unit test framework. See my another blog Simulate Mockito in ABAP for detail.

要获取更多Jerry的原创文章,请关注公众号"汪子熙":

SAP ABAP CGLIB(Code Generation Library)的模拟实现
            
    
    
        ABAPSAPSAP云平台SAP Cloud PlatformCloud