- 分组聚合使用场景
官网:比如菜单服务,接口一样,但有多种实现,用group区分,现在消费方需从每种group中调用一次返回结果,合并结果返回,这样就可以实现聚合菜单项。
自己理解:接口一样,不同的实现,可以将 不同的服务用 group 区分,调用的时候指定 group ,就能获取对应服务的结果
- 遇到的问题
在用 spring mvc 整合 dubbo 做分组聚合的时候配置如下
服务提供者
<bean id="mergeService" class="com.truthso.monitor.image.service.CompareServiceImpl"/>
<dubbo:service group="merge1" interface="com.truthso.monitor.image.service.CompareService" ref="mergeService"/>
<bean id="mergeService2" class="com.truthso.monitor.image.service.CompareServiceImpl2"/>
<dubbo:service group="merge2" interface="com.truthso.monitor.image.service.CompareService" ref="mergeService2"/>
有一个抽象接口 CompareService 两个接口实现 mergeService 分组为 merge1; mergeService2 分组为 merge2
服务消费者
<dubbo:reference id="mergeService" interface="com.truthso.monitor.image.service.CompareService" group="*" merger="true"/>
指定 group 为 *,merger 为 true
这样在调用的时候只需要普通的调用,方法返回的结果里面是两个实现的结果
@Controller
@RequestMapping("/index")
public class IndexController {
@Autowired
CompareService compareService;
@RequestMapping("home")
@ResponseBody
public String home() {
List<String> result = compareService.mergeResult();
System.out.println(result);
return "OK";
}
}
但是在 Spring boot 里面使用注解的方式 @Reference 有参数 group 并没有参数 merge,使用的时候,只能调用到一个接口实现的结果
@RestController
public class DemoController {
private static final Logger logger = LoggerFactory.getLogger(DemoController.class);
@Reference(version = "1.0.0", group = "*")
private DemoService demoService;
@RequestMapping("/hello/{name}")
public String sayHello(@PathVariable String name) {
List<Integer> list = demoService.getAll();
System.out.println(list);
// String str = demoService.sayHello(name);
return "mother fucker";
}
}
- 解决过程
想着没有就给你加一个好了,就重写了一个 一样的 Reference 在最后面加上了代码 merger
String merger() default "true";
用 String 的 原因是在 org.apache.dubbo.config.AbstractMethodConfig 里面的 merger 也是 String 的
但是还是不生效,只能跟踪源码,注解的方式不外乎启动的时候扫描,然后反射获取一些属性,后面再拼装成连接 bubbo 的URL,所以追踪到 org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceBeanBuilder 这个类应该就是组装类似<dubbo:reference> 标签的类,在 preConfigureBean 里面 最后一行
// 在第 134 行
// Bind annotation attributes
dataBinder.bind(new AnnotationPropertyValuesAdapter(reference, applicationContext.getEnvironment(), IGNORE_FIELD_NAMES));
发现有bind参数的动作,发现在 org.apache.dubbo.config.spring.beans.factory.annotation.AnnotationPropertyValuesAdapter 57 行处有 getAttributes(annotation, propertyResolver, ignoreDefaultValue, ignoreAttributeNames) ,所以在 org.apache.dubbo.config.spring.util.AnnotationUtils.getAttributes 处发现代码
// 252 行
// ignore default attribute value
if (ignoreDefaultValue && nullSafeEquals(attributeValue, getDefaultValue(annotation, attributeName))) {
continue;
}
原来默认有值的参数被continue了,所以将自己设置的 merger 的默认值改为 "" 空串后,就能正常调用了.
- 总结
- 不清楚为什么默认有值的属性就continue了
- 不知道为啥这个注解不把 merger 加上呢,是出于什么考虑呢