导航目录
工具类ZCL_ABAP_DYNAMIC_PROXY_FACTORY
该工具类负责生产一个新的具有持久化存储的静态代理类:
class ZCL_ABAP_DYNAMIC_PROXY_FACTORY definition
public
final
create public .
public section.
class-methods GET_PROXY
importing
!IO_ORIGIN type ref to OBJECT
!IV_NEW_CLASS_NAME type STRING
!IV_PRE_EXIT type STRING
!IV_POST_EXIT type STRING
returning
value(RO_PROXY) type ref to OBJECT .
protected section.
private section.
class-data MS_VSEOCLASS type VSEOCLASS .
class-data MT_ATTRIBUTE type SEOO_ATTRIBUTES_R .
class-data MT_IMP_IF type SEOR_IMPLEMENTINGS_R .
class-data MT_METHODS type SEOO_METHODS_R .
class-data MT_PARAMETERS type SEOS_PARAMETERS_R .
class-data MV_INTERFACE_NAME type STRING .
class-data MV_METHOD_NAME type STRING .
class-data MT_SOURCECODE type SEO_METHOD_SOURCE_TABLE .
class-data MV_NEW_CLASS_NAME type STRING .
class-data MO_ORIGIN type ref to OBJECT .
class-data MV_PRE_EXIT type STRING .
class-data MV_POST_EXIT type STRING .
class-methods GENERATE_CLASS .
class-methods PREPARE_ATTR_AND_SIGNATURE .
class-methods PREPARE_SOURCE_CODE .
class-methods EXTRACT_INTERFACE_INFO
importing
!IO_ORIGIN type ref to OBJECT .
class-methods INIT
importing
!IV_NEW_CLASS_NAME type STRING
!IO_ORIGIN type ref to OBJECT
!IV_PRE_EXIT type STRING
!IV_POST_EXIT type STRING .
class-methods CREATE_INSTANCE
returning
value(RO_PROXY) type ref to OBJECT .
ENDCLASS.
CLASS ZCL_ABAP_DYNAMIC_PROXY_FACTORY IMPLEMENTATION.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Private Method ZCL_ABAP_DYNAMIC_PROXY_FACTORY=>CREATE_INSTANCE
* +-------------------------------------------------------------------------------------------------+
* | [<-()] RO_PROXY TYPE REF TO OBJECT
* +--------------------------------------------------------------------------------------</SIGNATURE>
method CREATE_INSTANCE.
TRY.
create object ro_proxy type (mv_new_class_name)
EXPORTING
io_origin = mo_origin.
CATCH cx_root INTO data(cx_root).
WRITE:/ 'instance created failed: ', cx_root->get_text( ).
ENDTRY.
endmethod.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Private Method ZCL_ABAP_DYNAMIC_PROXY_FACTORY=>EXTRACT_INTERFACE_INFO
* +-------------------------------------------------------------------------------------------------+
* | [--->] IO_ORIGIN TYPE REF TO OBJECT
* +--------------------------------------------------------------------------------------</SIGNATURE>
method EXTRACT_INTERFACE_INFO.
data(lo_class) = cast CL_ABAP_OBJECTDESCR( cl_abap_objectdescr=>describe_by_object_ref( io_origin ) ).
READ TABLE lo_class->interfaces INTO mv_interface_name INDEX 1 .
CHECK sy-subrc = 0.
"For demo purpose, I assume only one method in one interface
SELECT SINGLE cmpname INTO mv_method_name FROM seocompo
WHERE clsname = mv_interface_name.
endmethod.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Private Method ZCL_ABAP_DYNAMIC_PROXY_FACTORY=>GENERATE_CLASS
* +-------------------------------------------------------------------------------------------------+
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD generate_class.
CALL FUNCTION 'SEO_CLASS_CREATE_COMPLETE'
EXPORTING
devclass = '$TMP'
version = seoc_version_active
authority_check = abap_true
overwrite = abap_true
suppress_method_generation = abap_false
genflag = abap_false
method_sources = mt_sourcecode
suppress_dialog = abap_true
CHANGING
class = ms_vseoclass
methods = mt_methods
parameters = mt_parameters
implementings = mt_imp_if
attributes = mt_attribute
EXCEPTIONS
existing = 1
is_interface = 2
db_error = 3
component_error = 4
no_access = 5
other = 6
OTHERS = 7.
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Public Method ZCL_ABAP_DYNAMIC_PROXY_FACTORY=>GET_PROXY
* +-------------------------------------------------------------------------------------------------+
* | [--->] IO_ORIGIN TYPE REF TO OBJECT
* | [--->] IV_NEW_CLASS_NAME TYPE STRING
* | [--->] IV_PRE_EXIT TYPE STRING
* | [--->] IV_POST_EXIT TYPE STRING
* | [<-()] RO_PROXY TYPE REF TO OBJECT
* +--------------------------------------------------------------------------------------</SIGNATURE>
method GET_PROXY.
init( iv_new_class_name = iv_new_class_name io_origin = io_origin
iv_pre_exit = iv_pre_exit iv_post_exit = iv_post_exit ).
extract_interface_info( io_origin ).
prepare_source_code( ).
prepare_attr_and_signature( ).
generate_class( ).
ro_proxy = create_instance( ).
endmethod.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Private Method ZCL_ABAP_DYNAMIC_PROXY_FACTORY=>INIT
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_NEW_CLASS_NAME TYPE STRING
* | [--->] IO_ORIGIN TYPE REF TO OBJECT
* | [--->] IV_PRE_EXIT TYPE STRING
* | [--->] IV_POST_EXIT TYPE STRING
* +--------------------------------------------------------------------------------------</SIGNATURE>
method INIT.
clear: mv_interface_name, mv_method_name, mt_sourcecode,mt_sourcecode,
mt_imp_if, ms_vseoclass, mt_attribute,mt_parameters,mt_methods.
mv_new_class_name = iv_new_class_name.
mo_origin = io_origin.
mv_pre_exit = iv_pre_exit.
mv_post_exit = iv_post_exit.
endmethod.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Private Method ZCL_ABAP_DYNAMIC_PROXY_FACTORY=>PREPARE_ATTR_AND_SIGNATURE
* +-------------------------------------------------------------------------------------------------+
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD prepare_attr_and_signature.
DATA:ls_attribute LIKE LINE OF mt_attribute,
ls_parameter LIKE LINE OF mt_parameters,
ls_method LIKE LINE OF mt_methods.
ls_method-clsname = mv_new_class_name.
ls_method-cmpname = 'CONSTRUCTOR'.
ls_method-state = 1. "implemented
ls_method-exposure = 2. "public
APPEND ls_method TO mt_methods.
ls_parameter-clsname = mv_new_class_name.
ls_parameter-cmpname = 'CONSTRUCTOR'.
ls_parameter-version = 1.
ls_parameter-descript = 'Constructor automatically generated by Jerry'.
ls_parameter-type = 'OBJECT'."mv_interface_name.
ls_parameter-sconame = 'IO_ORIGIN'.
ls_parameter-cmptype = 1. "METHOD
ls_parameter-mtdtype = 0. "METHOD
ls_parameter-pardecltyp = 0. "IMPORTING
ls_parameter-parpasstyp = 1. "pass by reference
ls_parameter-typtype = 3. "type ref to
APPEND ls_parameter TO mt_parameters.
ls_attribute-clsname = mv_new_class_name.
ls_attribute-cmpname = 'MO_ORIGIN'.
ls_attribute-state = 1.
ls_attribute-attdecltyp = 0.
ls_attribute-attexpvirt = 0. "private
ls_attribute-typtype = 3. "type ref to
ls_attribute-type = 'OBJECT'."mv_interface_name.
APPEND ls_attribute TO mt_attribute.
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Private Method ZCL_ABAP_DYNAMIC_PROXY_FACTORY=>PREPARE_SOURCE_CODE
* +-------------------------------------------------------------------------------------------------+
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD prepare_source_code.
DATA: ls_method_source TYPE seo_method_source,
ls_imp_if TYPE seor_implementing_r,
ls_imp_det TYPE seoredef.
ms_vseoclass-clsname = mv_new_class_name.
ms_vseoclass-state = seoc_state_implemented.
ms_vseoclass-exposure = seoc_exposure_public.
ms_vseoclass-descript = `Dynamic proxy generated by Jerry's code`.
ms_vseoclass-langu = sy-langu.
ms_vseoclass-clsccincl = abap_true.
ms_vseoclass-unicode = abap_true.
ms_vseoclass-fixpt = abap_true.
ms_vseoclass-clsfinal = abap_true.
ls_imp_det = ls_imp_if-clsname = mv_new_class_name.
ls_imp_det = ls_imp_if-refclsname = mv_interface_name.
ls_imp_if-state = seoc_state_implemented.
APPEND ls_imp_if TO mt_imp_if.
CLEAR: ls_method_source.
DATA: lv_name TYPE string.
ls_method_source-cpdname = |{ mv_interface_name }~{ mv_method_name }|.
APPEND |{ mv_pre_exit }| TO ls_method_source-source.
APPEND |DATA(lo) = CAST { mv_interface_name }( mo_origin ).| to ls_method_source-source.
APPEND 'lo->print( ).' TO ls_method_source-source.
APPEND |{ mv_post_exit }| TO ls_method_source-source.
APPEND ls_method_source TO mt_sourcecode.
CLEAR: ls_method_source.
ls_method_source-cpdname = 'CONSTRUCTOR'.
APPEND 'mo_origin = io_origin.' TO ls_method_source-source.
APPEND ls_method_source TO mt_sourcecode.
ENDMETHOD.
ENDCLASS.
工具类zcl_abap_cglib_tool
这个类是Jerry仿照Java CGLIB(Code Generation Library)创建的, 针对传入的一个ABAP类,能创建一个生命周期只有当前会话(current session)内的代理类,该代理类是传入ABAP类的子类。这意味着传入的ABAP类必须能够被继承,不能被标记为final.
CLASS zcl_abap_cglib_tool DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
CLASS-METHODS get_proxy
IMPORTING
!iv_class_name TYPE string
!io_pre_exit TYPE REF TO if_preexit
!io_post_exit TYPE REF TO if_postexit
RETURNING
VALUE(ro_proxy) TYPE REF TO object .
PROTECTED SECTION.
PRIVATE SECTION.
CLASS-DATA mv_class_name TYPE string .
CLASS-DATA mt_source TYPE seop_source_string .
CLASS-DATA mo_proxy TYPE REF TO object .
CLASS-DATA mo_preexit TYPE REF TO if_preexit .
CLASS-DATA mo_postexit TYPE REF TO if_postexit .
CLASS-METHODS generate_proxy .
CLASS-METHODS get_source_code .
ENDCLASS.
CLASS ZCL_ABAP_CGLIB_TOOL IMPLEMENTATION.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Private Method ZCL_ABAP_CGLIB_TOOL=>GENERATE_PROXY
* +-------------------------------------------------------------------------------------------------+
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD generate_proxy.
DATA(lv_new_cls_name) = mv_class_name && '_SUB'.
DATA(lv_inherit) = |inheriting from { mv_class_name }|.
TRANSLATE lv_new_cls_name TO UPPER CASE.
TRY.
LOOP AT mt_source ASSIGNING FIELD-SYMBOL(<source1>) WHERE table_line CS mv_class_name.
REPLACE mv_class_name IN <source1> WITH lv_new_cls_name.
ENDLOOP.
LOOP AT mt_source ASSIGNING FIELD-SYMBOL(<source>) WHERE table_line CS mv_class_name.
DELETE mt_source INDEX ( sy-tabix + 1 ).
INSERT lv_inherit INTO mt_source INDEX ( sy-tabix + 1 ).
EXIT.
ENDLOOP.
GENERATE SUBROUTINE POOL mt_source NAME DATA(prog).
WRITE: / sy-subrc.
DATA(class) = |\\PROGRAM={ prog }\\CLASS={ lv_new_cls_name }|.
CREATE OBJECT mo_proxy TYPE (class).
CALL METHOD mo_proxy->('SET_PREEXIT')
EXPORTING
io_preexit = mo_preexit.
CALL METHOD mo_proxy->('SET_POSTEXIT')
EXPORTING
io_postexit = mo_postexit.
CATCH cx_root INTO DATA(cx_root).
WRITE: / cx_root->get_text( ).
ENDTRY.
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Public Method ZCL_ABAP_CGLIB_TOOL=>GET_PROXY
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_CLASS_NAME TYPE STRING
* | [--->] IO_PRE_EXIT TYPE REF TO IF_PREEXIT
* | [--->] IO_POST_EXIT TYPE REF TO IF_POSTEXIT
* | [<-()] RO_PROXY TYPE REF TO OBJECT
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD get_proxy.
mv_class_name = iv_class_name.
mo_preexit = io_pre_exit.
mo_postexit = io_post_exit.
CLEAR: mo_proxy.
get_source_code( ).
generate_proxy( ).
ro_proxy = mo_proxy.
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Private Method ZCL_ABAP_CGLIB_TOOL=>GET_SOURCE_CODE
* +-------------------------------------------------------------------------------------------------+
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD get_source_code.
DATA:
cifkey TYPE seoclskey,
clstype TYPE seoclstype,
source TYPE seop_source_string,
pool_source TYPE seop_source_string,
l_string TYPE string,
source_line TYPE LINE OF seop_source_string,
tabix TYPE sytabix,
includes TYPE seop_methods_w_include,
include TYPE seop_method_w_include,
cifref TYPE REF TO if_oo_clif_incl_naming,
clsref TYPE REF TO if_oo_class_incl_naming,
intref TYPE REF TO if_oo_interface_incl_naming.
cifkey-clsname = mv_class_name.
CALL METHOD cl_oo_include_naming=>get_instance_by_cifkey
EXPORTING
cifkey = cifkey
RECEIVING
cifref = cifref
EXCEPTIONS
OTHERS = 1.
ASSERT sy-subrc = 0.
APPEND 'program.' TO mt_source.
CHECK cifref->clstype = seoc_clstype_class.
clsref ?= cifref.
READ REPORT clsref->class_pool INTO pool_source.
READ REPORT clsref->locals_old INTO source.
LOOP AT source INTO source_line.
IF source_line NS '*"*'.
APPEND source_line TO mt_source..
ENDIF.
ENDLOOP.
READ REPORT clsref->locals_def INTO source.
LOOP AT source INTO source_line.
IF source_line NS '*"*'.
APPEND source_line TO mt_source..
ENDIF.
ENDLOOP.
READ REPORT clsref->locals_imp INTO source.
LOOP AT source INTO source_line.
IF source_line NS '*"*'.
APPEND source_line TO mt_source..
ENDIF.
ENDLOOP.
READ REPORT clsref->public_section INTO source.
LOOP AT source ASSIGNING FIELD-SYMBOL(<source_line>).
IF <source_line> NS '*"*'.
FIND REGEX '.*methods.*\.' IN <source_line> MATCH LENGTH DATA(lv_len).
IF sy-subrc = 0.
lv_len = lv_len - 1.
<source_line> = <source_line>+0(lv_len).
CONCATENATE <source_line> 'redefinition' '.' INTO <source_line> SEPARATED BY space.
ENDIF.
APPEND <source_line> TO mt_source.
ENDIF.
ENDLOOP.
APPEND 'methods SET_PREEXIT importing !IO_PREEXIT type ref to IF_PREEXIT .' TO mt_source.
APPEND 'methods SET_POSTEXIT importing !IO_POSTEXIT type ref to IF_POSTEXIT .' TO mt_source.
READ REPORT clsref->protected_section INTO source.
LOOP AT source INTO source_line.
IF source_line NS '*"*'.
APPEND source_line TO mt_source.
ENDIF.
ENDLOOP.
READ REPORT clsref->private_section INTO source.
LOOP AT source INTO source_line.
IF source_line NS '*"*'.
APPEND source_line TO mt_source.
ENDIF.
ENDLOOP.
APPEND 'data MO_PREEXIT type ref to IF_PREEXIT .' TO mt_source.
APPEND 'data MO_POSTEXIT type ref to IF_POSTEXIT .' TO mt_source.
CONCATENATE 'CLASS' cifkey 'IMPLEMENTATION' INTO l_string SEPARATED BY space.
LOOP AT pool_source FROM tabix INTO source_line.
IF source_line CS 'ENDCLASS'.
APPEND source_line TO mt_source..
ENDIF.
IF source_line CS l_string.
SKIP.
APPEND source_line TO mt_source..
tabix = sy-tabix.
EXIT.
ENDIF.
ENDLOOP.
includes = clsref->get_all_method_includes( ).
LOOP AT includes INTO include.
READ REPORT include-incname INTO source.
INSERT 'mo_preexit->execute( ).' INTO source INDEX 2.
INSERT 'mo_postexit->execute( ).' INTO source INDEX ( lines( source ) ).
LOOP AT source INTO source_line.
APPEND source_line TO mt_source..
ENDLOOP.
ENDLOOP.
APPEND 'method set_preexit. mo_preexit = IO_PREEXIT. endmethod.' TO mt_source.
APPEND 'method set_postexit. mo_postexit = IO_POSTEXIT. endmethod.' TO mt_source.
LOOP AT pool_source FROM tabix INTO source_line.
IF source_line CS 'ENDCLASS'.
APPEND source_line TO mt_source..
ENDIF.
ENDLOOP.
ENDMETHOD.
ENDCLASS.
Jerry Wang的ABAP专题文章
- Jerry的ABAP, Java和JavaScript乱炖
- ABAP开发人员未来应该学些什么
- Jerry 2017年的五一小长假:8种经典排序算法的ABAP实现
- Jerry的ABAP原创技术文章合集
- 300行ABAP代码实现一个最简单的区块链原型
- 使用Java+SAP云平台+SAP Cloud Connector调用ABAP On-Premise系统里的函数
- 在SAP云平台的CloudFoundry环境下消费ABAP On-Premise OData服务
- ABAP vs Java, 蛙泳 vs 自由泳
- 聊聊C语言和ABAP
- 动手使用ABAP Channel开发一些小工具,提升日常工作效率
- 我用ABAP做过的那些无聊的事情
- 不喜欢SAP GUI?那试试用Eclipse进行ABAP开发吧
- 使用Visual Studio Code编写和激活ABAP代码
- 你的ABAP程序给佛祖开过光么?来试试Jerry这个小技巧
- 在SAP云平台ABAP编程环境上编写第一段ABAP程序
- SAP官方发布的ABAP编程规范
- ABAP Code Inspector那些隐藏的功能,您都知道吗?
- 还在用ABAP进行SAP产品的二次开发?来了解下这种全新的二次开发理念吧
- ABAP Netweaver体内的那些寄生式编程语言
- 从SAP社区上的一篇博客开始,聊聊SAP产品命名背后的那份情怀
- 云端的ABAP Restful服务开发
- 如何在SAP云平台ABAP编程环境里把CDS view暴露成OData服务
- 使用abapGit在ABAP On-Premises系统和SAP云平台ABAP环境之间进行代码传输
- 30分钟用Restful ABAP Programming模型开发一个支持增删改查的Fiori应用
- Jerry带您了解Restful ABAP Programming模型系列之二:Action和Validation的实现
- Jerry带您了解Restful ABAP Programming模型系列之三:云端ABAP应用调试
- SAP云平台上的ABAP编程环境里如何消费第三方服务
- ABAP开发者上云的时候到了 - 现在大家可以免费使用SAP云平台ABAP环境的试用版了
- 学而不思则罔 - SAP云平台ABAP编程环境的由来和适用场景
- SAP云平台里的三叉戟应用
- 如何基于Restful ABAP Programming模型开发并部署一个支持增删改查的Fiori应用
- SAP 2019 TechEd Key Note解读:云时代下SAP从业人员如何做二次开发?
- 有哪些ABAP关键字和语法,到了ABAP云环境上就没办法用了?
- ABAP开发环境终于支持以驼峰命名法自动格式化ABAP变量名了
- 利用ABAP 740的新关键字REDUCE完成一个实际工作任务
- 一段让人瑟瑟发抖的ABAP代码
- 昨日万圣节ABAP怪兽级代码谜团,公布答案啦
- 介绍一种在ABAP内核态进行内表高效拷贝的方法
- 使用SAP Cloud Application Programming模型开发OData的一个实际例子
- 当ABAP遇见普罗米修斯
- 使用ABAP绘制可伸缩矢量图
- ABAP开发环境语法高亮的那些事儿
- SAP错误消息调试之七种武器:让所有的错误消息都能被定位
- 使用ABAP操作Excel的几种方法
- SAP GUI里的收藏夹事务码管理工具
- SAP GUI和Windows注册表
- 有了Debug权限就能干坏事?小心了,你的一举一动尽在系统监控中
- ABAP CCDEF, CCIMP, CCMAC, CCAU, CMXXX这些东东是什么鬼
- 实现ABAP条件断点的三种方式
- 使用SAT跟踪监控从浏览器打开的SAP应用的性能和调用栈
- 一个13年ABAP老兵的建议:了解这些基础知识,对ABAP开发有百利而无一害
- SAP ABAP Netweaver容器化, 不可能完成的任务吗?
- SAP产品增强技术回顾
- SAP API开发方法大全