原文链接
该工具类负责生产一个新的具有持久化存储的静态代理类:
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.
* ---------------------------------------------------------------------------------------+
* | Static Private Method ZCL_ABAP_DYNAMIC_PROXY_FACTORY=>CREATE_INSTANCE
* +-------------------------------------------------------------------------------------------------+
* | [<-()] RO_PROXY TYPE REF TO OBJECT
* +--------------------------------------------------------------------------------------
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.
* ---------------------------------------------------------------------------------------+
* | Static Private Method ZCL_ABAP_DYNAMIC_PROXY_FACTORY=>EXTRACT_INTERFACE_INFO
* +-------------------------------------------------------------------------------------------------+
* | [--->] IO_ORIGIN TYPE REF TO OBJECT
* +--------------------------------------------------------------------------------------
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.
* ---------------------------------------------------------------------------------------+
* | Static Private Method ZCL_ABAP_DYNAMIC_PROXY_FACTORY=>GENERATE_CLASS
* +-------------------------------------------------------------------------------------------------+
* +--------------------------------------------------------------------------------------
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.
* ---------------------------------------------------------------------------------------+
* | 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
* +--------------------------------------------------------------------------------------
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.
* ---------------------------------------------------------------------------------------+
* | 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
* +--------------------------------------------------------------------------------------
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.
* ---------------------------------------------------------------------------------------+
* | Static Private Method ZCL_ABAP_DYNAMIC_PROXY_FACTORY=>PREPARE_ATTR_AND_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.
* ---------------------------------------------------------------------------------------+
* | Static Private Method ZCL_ABAP_DYNAMIC_PROXY_FACTORY=>PREPARE_SOURCE_CODE
* +-------------------------------------------------------------------------------------------------+
* +--------------------------------------------------------------------------------------
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.
这个类是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.
* ---------------------------------------------------------------------------------------+
* | Static Private Method ZCL_ABAP_CGLIB_TOOL=>GENERATE_PROXY
* +-------------------------------------------------------------------------------------------------+
* +--------------------------------------------------------------------------------------
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() WHERE table_line CS mv_class_name.
REPLACE mv_class_name IN WITH lv_new_cls_name.
ENDLOOP.
LOOP AT mt_source ASSIGNING FIELD-SYMBOL(
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开发方法大全