现象
应用任务运行异常{code}
Caused by: java.lang.IllegalStateException: Duplicate spring bean id realnameAuthPubService
at com.alibaba.dubbo.rpc.config.spring.schema.DubboBeanDefinitionParser.parse(DubboBeanDefinitionParser.java:87)
at com.alibaba.dubbo.rpc.config.spring.schema.DubboBeanDefinitionParser.parse(DubboBeanDefinitionParser.java:63)
at org.springframework.beans.factory.xml.NamespaceHandlerSupport.parse(NamespaceHandlerSupport.java:69)
at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1297)
at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1287)
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:135)
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.registerBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:92)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.registerBeanDefinitions(XmlBeanDefinitionReader.java:507)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:398)
{code}
排查
查看代码,确实有id为realnameAuthPubService的重复配置,不过已经存在很久了,之前都没有问题。
问题出现的当天仅有dubbo升级需求发布,所以定位到是dubbo升级引发了这个一直存在的问题
原因
spring对于id重复的默认处理策略是覆盖,如DefaultListableBeanFactory.registerBeanDefinition,dubbo之前没做特殊处理,所以对重复的id会覆盖,所以一直没有报错
{code}
...
synchronized (this.beanDefinitionMap) {
Object oldBeanDefinition = this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) {
##allowBeanDefinitionOverriding默认值为ture
if (!this.allowBeanDefinitionOverriding) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
"': There is already [" + oldBeanDefinition + "] bound.");
}
else {
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName +
"': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
}
}
else {
this.beanDefinitionNames.add(beanName);
this.frozenBeanDefinitionNames = null;
}
##如果原来有,覆盖
this.beanDefinitionMap.put(beanName, beanDefinition);
...
{code}
dubbo的新版本对重复的id做了特殊处理,如果有重复直接抛异常,所以出现问题
{code}
DubboBeanDefinitionParser.parse
private BeanDefinition parse(Element element, ParserContext parserContext, Class<?> beanClass, boolean required) {
...
if (id != null && id.length() > 0) {
###判断是否已经存在,存在则抛出异常
if (parserContext.getRegistry().containsBeanDefinition(id)) {
throw new IllegalStateException("Duplicate spring bean id " + id);
}
parserContext.getRegistry().registerBeanDefinition(id, beanDefinition);
}
...
}
{code}