想在服务启动的时候,将所有的 service 存放到一个缓存 Map 中,然后给定一个 key 值绑定。 在 controller 中通过 key 值找到对应的 service 对象该如何实现。 因为不同 service 的类型不一样,所以 Map 在定义的时候只能定义成 Map<String,Object>value 是个 Object, 这样的话通过 key 值取出来的也就是 Object 的类型,无法调用到 service 下的方法。 有没有好的实现思路呢?
1
tsening 2020-09-03 11:16:12 +08:00
我累了,小白吧。。。
|
2
mosliu 2020-09-03 11:17:00 +08:00
反射呗
|
3
chendy 2020-09-03 11:17:41 +08:00
为啥要这么搞,别的不说,service 的参数和返回也不一样啊
|
4
jiobanma OP @chendy #3 因为服务要做成动态的,service 里面只有一个通用接口,参数都是 Map 所以不存在返回值类型和参数不同的问题
|
6
pushback 2020-09-03 11:32:00 +08:00
method.invoke
|
7
pushback 2020-09-03 11:33:09 +08:00
存储 class 就行,对应 value 到 BeanFactory 下去取
|
8
idoggy 2020-09-03 11:35:01 +08:00 via Android 1
入参都一样吗?要调用的 service 全部继承同一个接口就行了,用 applicationcontext.getbean 去调。
|
9
ily433664 2020-09-03 11:40:21 +08:00
通过 applicationContext 获取,可以根据 bean 类型或者名称
|
11
lipcao 2020-09-03 11:56:22 +08:00
哈哈,你这个标准的策略+工厂模式 解决 if else 啊,前一段时间公众号嗷嗷推这个。。。
|
12
zhuweiyou 2020-09-03 11:57:32 +08:00 1
建议楼主学 PHP 或 JS,他们就是这么玩的。
|
13
DelayNoMay 2020-09-03 12:00:08 +08:00
用 golang 的 interface
|
14
yuan7712 2020-09-03 12:03:11 +08:00
|
15
460881773 2020-09-03 12:04:35 +08:00
花里胡哨
|
16
aguesuka 2020-09-03 12:06:47 +08:00 via Android
service 都带个 controller,原来的 controller 里通过 key 转发到对应的 service 的 controller 。param bind 是 spring 的工作,不要实现一个低配版的
|
17
aguesuka 2020-09-03 12:10:16 +08:00 via Android 1
以前我还是个傻逼的时候,map 里面存的是个 lambda 函数,比如 map.put(key,xxxxService::doxxxxxxx)
|
18
huifer 2020-09-03 12:17:25 +08:00
添加一个 接口比如
```java public interface KeyInterface{ String key(); } ``` - 所有 service 都实现这个接口,重写 key() - 在启动阶段(ApplicationRunner 或者 CommandLineRunner)通过 context.getBeanOfTypes(KeyInterface.class) 获取到一个 map key: beanName value: KeyInterface 的实现 - 调用 value 的 key()方法. 将结果映射成 key:key() ,value: service 即可 |
19
dutianze 2020-09-03 13:11:45 +08:00
如果所有 sevice 都是同样的接口的话,
1. 所有 service 都继承一个接口 CommonService 2. @Autowired private Map<String, CommonService> commonServiceMap; k 默认是 service 的类名小写,v 默认是对应的 service |
20
butterfly1211 2020-09-03 13:13:28 +08:00
服务注册与服务发现
|
21
24bit 2020-09-03 13:16:57 +08:00
不如直接用注解标注要缓存的方法,直接在 Map 里面存 Method,取的时候直接调用
|
22
Cyron 2020-09-03 13:19:33 +08:00
Service service = applicationContext.getBean("serviceImplA");
Service service = applicationContext.getBean("serviceImplB"); |
23
jintianfengda 2020-09-03 14:28:27 +08:00
用 map 这么玩开发一时爽,维护火葬场
|
24
ixx 2020-09-03 14:55:18 +08:00
|
25
liuguangcuican 2020-09-03 15:12:58 +08:00 via Android
|
26
d460686680 2020-09-03 15:24:21 +08:00
实现同一个接口 + getBean()
|
27
levizheng 2020-09-03 15:36:41 +08:00
简单工厂就可以解决了。。 放一 map 里
|
28
xuanbg 2020-09-03 16:16:29 +08:00
我司的 php 写的老系统就是这样,接口参数里面有个 action,1234567……分别对应一个方法。。。。各方法传入一个 object,其实就是一个 json,各个方法自己负责解析这个参数。楼主莫非要的是这个?
可是为啥不把接口拆开呢? |
29
KevinBlandy 2020-09-03 16:26:15 +08:00
ApplicationContext.getBean();
|
30
ocean1477 2020-09-03 16:30:24 +08:00
策略模式了解下
|
31
caotian 2020-09-03 16:38:23 +08:00
不要手工维护 map, 不然每次加一个 serivce 还要修改这个 map
可以这样试试: 每个 service 定义自己的 key, 实现同一个接口 IService, 使用的时候通过 Autowired 注入拿到 List<IService>对象, 通过 key 来获得具体的 service 实例, 再调用方法 |
33
pierswu 2020-09-03 16:52:43 +08:00
这个用 mvc 的 forward 不就行了吗?
每一个 service 都有各自的 controller,就按照正常的写 ,然后总的 controller 根据不同的 key,forward 到不同的 controller 至于 key,最好能放在 url 中或者 header 中,好取一些 |
34
pierswu 2020-09-03 16:57:54 +08:00
用 forward 的话,每个 service 的参数类型,参数个数,返回值,都可以不一样的
|
35
pengfei 2020-09-03 17:31:53 +08:00
策略模式 ?
|
36
venpong 2020-09-03 18:05:50 +08:00
建议学学设计模式,比如楼上说的策略模式就可以很优雅的解决你这个问题。
|
37
oneisall8955 2020-09-03 18:24:36 +08:00 via Android 1
我最喜欢搞这些花里胡哨得了,经常写工厂模式+模板
|
38
securityCoding 2020-09-03 18:40:46 +08:00
applicationContext.getBean()
策略模式+泛型可解 不过在业务层做这种事情这种看起来很无脑....中间件还情有可原 |
39
BigBunny 2020-09-03 20:03:39 +08:00
做那种对外开放平台标准化接口有用过。当时的想法是 controller 里所有接口的请求参数返回参数都一样。加签验签逻辑也都一致。索性共用一个接口,调用 service 里的方法通过自定义注解去区分。半路转的 java,也不知道这么做了对不对好不好。
|
40
supermoonie 2020-09-03 20:12:26 +08:00 via iPhone
注解?
|
41
chachae 2020-09-03 20:45:55 +08:00
策略模式
|
42
gaius 2020-09-04 01:23:30 +08:00 via Android
以前掉各种银行接口就是用反射,配置全限定名
|
43
1ffree 2020-09-04 09:56:48 +08:00
19l 正解 +1
|
44
HolmLoh 2020-09-04 10:26:26 +08:00
工厂模式加模板模式,小的单人开发的项目这么搞搞还行,偷偷懒还挺快乐,人多起来不好维护
|
45
yisheyuanzhang 2020-09-04 10:51:46 +08:00
想到两种方法
1 、8L 的方法,Service 实现同一接口,key 作为 bean 的名称,用 applicationcontext.getbean 去调。缺点是每个 service 只能实现同一个方法。 2 、定义 service 的类注解和方法注解, 启动时通过 BeanPostProcessor,根据类注解的 key 存入 Map<key,bean>中。调用时根据类注解 key,找到 bean,根据方法注解 key 找到方法,通过反射执行 我们生产中用过第二种 |
46
CoderGeek 2020-09-04 13:54:15 +08:00
简单点
1. <String,String> key 是你的策略 value 是你的 beanName 直接 get 就好 2. <String,Class> key 是你的策略 value 是你的所有加载的 service 取出来强制转型 3.直接用 xml 更简单创建一个 map 对象 value 是多个 bean 举个常见栗子 private Map<Object, Object> targetDataSources; <bean id="xxx" class="xxxxx"> <property name="targetDataSources"> <map> <entry key="xxxxx" value-ref="xxxxx"></entry> </map> </property> </bean> |
47
6IbA2bj5ip3tK49j 2020-09-04 13:56:27 +08:00
别听楼上 BB 。
把那些 service 合成一个函数方法就 ok 了。 一个函数就解决所有问题了,高内聚。 传来 map,返回 map,改动也只需要改这一个函数,低耦合。 |
48
xiaoxinshiwo 2020-09-04 15:38:59 +08:00
instance of
|
49
yazinnnn 2020-09-05 22:14:12 +08:00
```kotlin
@RestController class ControllerA( var serviceA: ServiceA, var serviceB: ServiceB ) { @RequestMapping("/") fun foo(type: String, param: String) = serviceMap[type]!!(param) private val funcA = { it: String -> serviceA.foo(it) } private val funcB = { it: String -> serviceB.foo(it) } private val serviceMap by lazy { mutableMapOf( "a" to funcA, "b" to funcB ) } } ``` kotlin 可以这么干,java 没有 by lazy,估计比较啰嗦 |
50
Relims 2020-09-07 17:34:35 +08:00
value 存 service 的实例化对象,通过对象来调用方法,如果你的 sevice 有共同的方法的化,还可以用到工厂模式
|