在ABAP里模拟实现Java Spring的依赖注入 尝试的场景 ABAP Summer框架的消费代码 使用ABAP Summer框架实现依赖注入 ABAP Summer依赖注入的实现原理

Dependency Injection- 依赖注入,在Java Spring框架中有着广泛地应用。通过依赖注入,我们不必在应用代码里繁琐地初始化依赖的资源,非常方便。

那么ABAP能否从语言层面上也支持依赖注入,享受这种设计思路带来的便利呢?让我们做一次尝试。

在现实生活中,每一盏灯都有一个开关控制。按下开关,灯被打开;再按一次,灯熄灭。

先看不使用依赖注入的常规实现:

设计一个ABAP interface ZIF_SWITCHABLE,提供两个方法,分别对应开和关。

在ABAP里模拟实现Java Spring的依赖注入
尝试的场景
ABAP Summer框架的消费代码
使用ABAP Summer框架实现依赖注入
ABAP Summer依赖注入的实现原理

自然的,我有一个ABAP 类 ZCL_LAMP,用于实现上述接口。每个ZCL_LAMP的实例就是一盏灯。

CLASS ZCL_LAMP IMPLEMENTATION.

method ZIF_SWITCHABLE~OFF.

WRITE: / 'lamp off'.

endmethod.

method ZIF_SWITCHABLE~ON.

WRITE: / 'lamp on'.

endmethod.

ENDCLASS.

再设计一个开关类,这个类有一个成员变量mo_switchable, 指向ZIF_SWITCHABLE这个接口。

在ABAP里模拟实现Java Spring的依赖注入
尝试的场景
ABAP Summer框架的消费代码
使用ABAP Summer框架实现依赖注入
ABAP Summer依赖注入的实现原理

开关有个“按”的方法。按下之后,如果当前状态是开,那么就调用mo_switchable成员的off方法,将其关闭,并设置开关状态为关闭。反之亦然。

METHOD push.

IF isswitchon = abap_true.

mo_switchable->off( ).

isswitchon = abap_false.

ELSE.

mo_switchable->on( ).

isswitchon = abap_true.

ENDIF.

ENDMETHOD.

提供一个setter方法,将传入的类型为ZIF_SWITCHABLE的变量注入到成员变量mo_switchable中。

method SET_SWITCHABLE.

mo_switchable = io_switchable.

endmethod.

我把迄今为止创建的两个类:ZCL_LAMP和ZCL_SWITCH都放到package $ZDEV_INVERSION内。

在ABAP里模拟实现Java Spring的依赖注入
尝试的场景
ABAP Summer框架的消费代码
使用ABAP Summer框架实现依赖注入
ABAP Summer依赖注入的实现原理

ABAP Summer框架的消费代码

从下图的代码能看出,ZCL_SWITCH和ZCL_LAMP产生了强依赖关系。这种依赖关系是应用开发人员调用set方法手动注入的。

在ABAP里模拟实现Java Spring的依赖注入
尝试的场景
ABAP Summer框架的消费代码
使用ABAP Summer框架实现依赖注入
ABAP Summer依赖注入的实现原理

总结一下,上图代码有哪些是在Java Spring里完全能够通过依赖注入的思想来避免的。

line 8: 手工创建ZCL_LAMP(灯)的实例。

line 9: 手工创建ZCL_SWITCH(开关)的实例。

line 11: 调用set方法手动注入灯和开关的依赖关系。

使用ABAP Summer框架实现依赖注入

我自己用ABAP模拟了Java Spring的依赖注入框架,开发了一个原型,取名ABAP Summer,与Java的Spring相呼应。

先想想这个简单的例子用Java Spring如何实现。一个Java程序员很容易就能写出下面的代码,利用Spring的注解@Inject,我们无需手动实例化ISwitchable和调用set方法建立依赖。一切由Spring框架帮我们实现了。

在ABAP里模拟实现Java Spring的依赖注入
尝试的场景
ABAP Summer框架的消费代码
使用ABAP Summer框架实现依赖注入
ABAP Summer依赖注入的实现原理

现在,怎样用ABAP实现这些“魔术”?

1. 在ZCL_SWITCH类的成员变量mo_switchable的描述字段里加上注解@Inject,意图是告诉ABAP Summer框架,我希望mo_switchable成员能够自动被注入一个正确的依赖进来。到底什么样的依赖算正确?Summer框架如何知道该怎样注入?请继续阅读。

在ABAP里模拟实现Java Spring的依赖注入
尝试的场景
ABAP Summer框架的消费代码
使用ABAP Summer框架实现依赖注入
ABAP Summer依赖注入的实现原理

注意:ABAP这门语言同Java不同,无法在语言层面支持注解,因此这里在Description字段上维护的@Inject只是一个模拟。

2. 先看采用了依赖注入之后的ABAP消费代码,是不是一下子清爽了很多?

data(summer) = zcl_summer=>get_instance( ).

data(lo_switch) = cast zcl_switch( summer->get_bean( EXPORTING iv_bean_name = 'ZCL_SWITCH' ) ).

lo_switch->push( ).

lo_switch->push( ).

下图是基于ABAP常规实现和基于ABAP依赖注入思想的两套消费代码的比较,能清晰发现,采取了ABAP依赖注入后,

在ABAP里模拟实现Java Spring的依赖注入
尝试的场景
ABAP Summer框架的消费代码
使用ABAP Summer框架实现依赖注入
ABAP Summer依赖注入的实现原理

之前提到的这三处手动操作完全得到避免。GET_BEAN方法返回的开关实例,里面的成员变量mo_switchable包含的就是自动注入好的ZCL_LAMP类的实例。

line 8: 手工创建ZCL_LAMP(灯)的实例。

line 9: 手工创建ZCL_SWITCH(开关)的实例。

line 11: 调用set方法手动注入灯和开关的依赖关系。

让我们再看看Java Spring里正宗的消费代码,确保我们发明的ABAP Summer确实是原汁原味的依赖注入。

在ABAP里模拟实现Java Spring的依赖注入
尝试的场景
ABAP Summer框架的消费代码
使用ABAP Summer框架实现依赖注入
ABAP Summer依赖注入的实现原理

ABAP Summer依赖注入的实现原理

这个ABAP依赖注入框架的实现在我的github上:

https://github.com/i042416/jerryslide/tree/master/ABAP/summer

在ABAP里模拟实现Java Spring的依赖注入
尝试的场景
ABAP Summer框架的消费代码
使用ABAP Summer框架实现依赖注入
ABAP Summer依赖注入的实现原理

关于Java Spring依赖注入的讲解,网上有很多写得很精彩的著作。

在ABAP里模拟实现Java Spring的依赖注入
尝试的场景
ABAP Summer框架的消费代码
使用ABAP Summer框架实现依赖注入
ABAP Summer依赖注入的实现原理

下面是ABAP Summer依赖注入的核心实现,参考了上图著作关于Java Spring的讲解。

在ABAP里模拟实现Java Spring的依赖注入
尝试的场景
ABAP Summer框架的消费代码
使用ABAP Summer框架实现依赖注入
ABAP Summer依赖注入的实现原理

要获取更多Jerry的原创技术文章,请关注公众号"汪子熙"或者扫描下面二维码:
在ABAP里模拟实现Java Spring的依赖注入
尝试的场景
ABAP Summer框架的消费代码
使用ABAP Summer框架实现依赖注入
ABAP Summer依赖注入的实现原理

在ABAP里模拟实现Java Spring的依赖注入
尝试的场景
ABAP Summer框架的消费代码
使用ABAP Summer框架实现依赖注入
ABAP Summer依赖注入的实现原理