Jerry文章《浅谈Java和SAP ABAP的静态代理和动态代理,以及ABAP面向切面编程的尝试一文的源代码》
原文鏈接
導(dǎo)航目錄
- 工具類ZCL_ABAP_DYNAMIC_PROXY_FACTORY
- 工具類zcl_abap_cglib_tool
- Jerry Wang的ABAP專題文章
工具類ZCL_ABAP_DYNAMIC_PROXY_FACTORY
該工具類負(fù)責(zé)生產(chǎn)一個(gè)新的具有持久化存儲(chǔ)的靜態(tài)代理類:
class ZCL_ABAP_DYNAMIC_PROXY_FACTORY definitionpublicfinalcreate public .public section.class-methods GET_PROXYimporting!IO_ORIGIN type ref to OBJECT!IV_NEW_CLASS_NAME type STRING!IV_PRE_EXIT type STRING!IV_POST_EXIT type STRINGreturningvalue(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_INFOimporting!IO_ORIGIN type ref to OBJECT .class-methods INITimporting!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_INSTANCEreturningvalue(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)EXPORTINGio_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 interfaceSELECT SINGLE cmpname INTO mv_method_name FROM seocompoWHERE 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'EXPORTINGdevclass = '$TMP'version = seoc_version_activeauthority_check = abap_trueoverwrite = abap_truesuppress_method_generation = abap_falsegenflag = abap_falsemethod_sources = mt_sourcecodesuppress_dialog = abap_trueCHANGINGclass = ms_vseoclassmethods = mt_methodsparameters = mt_parametersimplementings = mt_imp_ifattributes = mt_attributeEXCEPTIONSexisting = 1is_interface = 2db_error = 3component_error = 4no_access = 5other = 6OTHERS = 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_originiv_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. "implementedls_method-exposure = 2. "publicAPPEND 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. "METHODls_parameter-mtdtype = 0. "METHODls_parameter-pardecltyp = 0. "IMPORTINGls_parameter-parpasstyp = 1. "pass by referencels_parameter-typtype = 3. "type ref toAPPEND 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. "privatels_attribute-typtype = 3. "type ref tols_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
這個(gè)類是Jerry仿照J(rèn)ava CGLIB(Code Generation Library)創(chuàng)建的, 針對(duì)傳入的一個(gè)ABAP類,能創(chuàng)建一個(gè)生命周期只有當(dāng)前會(huì)話(current session)內(nèi)的代理類,該代理類是傳入ABAP類的子類。這意味著傳入的ABAP類必須能夠被繼承,不能被標(biāo)記為final.
CLASS zcl_abap_cglib_tool DEFINITIONPUBLICFINALCREATE PUBLIC .PUBLIC SECTION.CLASS-METHODS get_proxyIMPORTING!iv_class_name TYPE string!io_pre_exit TYPE REF TO if_preexit!io_post_exit TYPE REF TO if_postexitRETURNINGVALUE(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')EXPORTINGio_preexit = mo_preexit.CALL METHOD mo_proxy->('SET_POSTEXIT')EXPORTINGio_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_cifkeyEXPORTINGcifkey = cifkeyRECEIVINGcifref = cifrefEXCEPTIONSOTHERS = 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開(kāi)發(fā)人員未來(lái)應(yīng)該學(xué)些什么
-
Jerry 2017年的五一小長(zhǎng)假:8種經(jīng)典排序算法的ABAP實(shí)現(xiàn)
-
Jerry的ABAP原創(chuàng)技術(shù)文章合集
-
300行ABAP代碼實(shí)現(xiàn)一個(gè)最簡(jiǎn)單的區(qū)塊鏈原型
-
使用Java+SAP云平臺(tái)+SAP Cloud Connector調(diào)用ABAP On-Premise系統(tǒng)里的函數(shù)
-
在SAP云平臺(tái)的CloudFoundry環(huán)境下消費(fèi)ABAP On-Premise OData服務(wù)
-
ABAP vs Java, 蛙泳 vs 自由泳
-
聊聊C語(yǔ)言和ABAP
-
動(dòng)手使用ABAP Channel開(kāi)發(fā)一些小工具,提升日常工作效率
-
我用ABAP做過(guò)的那些無(wú)聊的事情
-
不喜歡SAP GUI?那試試用Eclipse進(jìn)行ABAP開(kāi)發(fā)吧
-
使用Visual Studio Code編寫(xiě)和激活A(yù)BAP代碼
-
你的ABAP程序給佛祖開(kāi)過(guò)光么?來(lái)試試Jerry這個(gè)小技巧
-
在SAP云平臺(tái)ABAP編程環(huán)境上編寫(xiě)第一段ABAP程序
-
SAP官方發(fā)布的ABAP編程規(guī)范
-
ABAP Code Inspector那些隱藏的功能,您都知道嗎?
-
還在用ABAP進(jìn)行SAP產(chǎn)品的二次開(kāi)發(fā)?來(lái)了解下這種全新的二次開(kāi)發(fā)理念吧
-
ABAP Netweaver體內(nèi)的那些寄生式編程語(yǔ)言
-
從SAP社區(qū)上的一篇博客開(kāi)始,聊聊SAP產(chǎn)品命名背后的那份情懷
-
云端的ABAP Restful服務(wù)開(kāi)發(fā)
-
如何在SAP云平臺(tái)ABAP編程環(huán)境里把CDS view暴露成OData服務(wù)
-
使用abapGit在ABAP On-Premises系統(tǒng)和SAP云平臺(tái)ABAP環(huán)境之間進(jìn)行代碼傳輸
-
30分鐘用Restful ABAP Programming模型開(kāi)發(fā)一個(gè)支持增刪改查的Fiori應(yīng)用
-
Jerry帶您了解Restful ABAP Programming模型系列之二:Action和Validation的實(shí)現(xiàn)
-
Jerry帶您了解Restful ABAP Programming模型系列之三:云端ABAP應(yīng)用調(diào)試
-
SAP云平臺(tái)上的ABAP編程環(huán)境里如何消費(fèi)第三方服務(wù)
-
ABAP開(kāi)發(fā)者上云的時(shí)候到了 - 現(xiàn)在大家可以免費(fèi)使用SAP云平臺(tái)ABAP環(huán)境的試用版了
-
學(xué)而不思則罔 - SAP云平臺(tái)ABAP編程環(huán)境的由來(lái)和適用場(chǎng)景
-
SAP云平臺(tái)里的三叉戟應(yīng)用
-
如何基于Restful ABAP Programming模型開(kāi)發(fā)并部署一個(gè)支持增刪改查的Fiori應(yīng)用
-
SAP 2019 TechEd Key Note解讀:云時(shí)代下SAP從業(yè)人員如何做二次開(kāi)發(fā)?
-
有哪些ABAP關(guān)鍵字和語(yǔ)法,到了ABAP云環(huán)境上就沒(méi)辦法用了?
-
ABAP開(kāi)發(fā)環(huán)境終于支持以駝峰命名法自動(dòng)格式化ABAP變量名了
-
利用ABAP 740的新關(guān)鍵字REDUCE完成一個(gè)實(shí)際工作任務(wù)
-
一段讓人瑟瑟發(fā)抖的ABAP代碼
-
昨日萬(wàn)圣節(jié)ABAP怪獸級(jí)代碼謎團(tuán),公布答案啦
-
介紹一種在ABAP內(nèi)核態(tài)進(jìn)行內(nèi)表高效拷貝的方法
-
使用SAP Cloud Application Programming模型開(kāi)發(fā)OData的一個(gè)實(shí)際例子
-
當(dāng)ABAP遇見(jiàn)普羅米修斯
-
使用ABAP繪制可伸縮矢量圖
-
ABAP開(kāi)發(fā)環(huán)境語(yǔ)法高亮的那些事兒
-
SAP錯(cuò)誤消息調(diào)試之七種武器:讓所有的錯(cuò)誤消息都能被定位
-
使用ABAP操作Excel的幾種方法
-
SAP GUI里的收藏夾事務(wù)碼管理工具
-
SAP GUI和Windows注冊(cè)表
-
有了Debug權(quán)限就能干壞事?小心了,你的一舉一動(dòng)盡在系統(tǒng)監(jiān)控中
-
ABAP CCDEF, CCIMP, CCMAC, CCAU, CMXXX這些東東是什么鬼
-
實(shí)現(xiàn)ABAP條件斷點(diǎn)的三種方式
-
使用SAT跟蹤監(jiān)控從瀏覽器打開(kāi)的SAP應(yīng)用的性能和調(diào)用棧
-
一個(gè)13年ABAP老兵的建議:了解這些基礎(chǔ)知識(shí),對(duì)ABAP開(kāi)發(fā)有百利而無(wú)一害
-
SAP ABAP Netweaver容器化, 不可能完成的任務(wù)嗎?
-
SAP產(chǎn)品增強(qiáng)技術(shù)回顧
-
SAP API開(kāi)發(fā)方法大全
總結(jié)
以上是生活随笔為你收集整理的Jerry文章《浅谈Java和SAP ABAP的静态代理和动态代理,以及ABAP面向切面编程的尝试一文的源代码》的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: IDEA Translation插件中有
- 下一篇: 奇迹MU最强者剑士怎么样 奇迹MU最强者