【邪修编程】忽略Spring启动时,同名Bean报错问题,先让服务启动起来。「spring.main.allow-bean-definition-overriding=true」
目录
隐患二:按名称注入(@Resource(name = "user"))会取错对象
==
■前言
基盘代码貌似有问题呀。。。。
(工程里面 和 服务器使用的jar里面,有不同包,同名的类,即SpringBean同名。。。)
Project AAA中,有aaa.bbb.ccc.gen.mapper.TTBean
Project AAA中,使用AAA-bb-main.jar
AAA-bb-main.jar中,有aaa.bbb.ccc.mapper.TTBean
TTBean重复了。。。。
Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException:
Annotation-specified bean name 'xxxx' for bean class [aaa.bbb.ccc.gen.mapper.TTBean] conflicts with existing,
non-compatible bean definition of same name and class [aaa.bbb.ccc.mapper.TTBean]
把这个基盘代码,Bean重复的问题提了出去,
那边的开发说什么使用 MyBatis的FQDN可以解决。
可是查了一下,MyBatis的FQDN解决不了Spring的同名Bean冲突问题。
====

===
■吐槽
===
NTT DATA 的 Imart 产品,
不用Maven管理第三方jar。。。
(生成war包的时候,使用一个叫Juggling的东西)
是Resin的Accel PlateForm Library ,其中一个AAA-bb.jar还是后期修改的。
完全TMD不整合。。。。
(IMart.war /WEB-INF/Lib/*.jar)
====
■暂时解决策
Resin的JVM启动参数中,添加下面内容:
spring.main.allow-bean-definition-overriding=true
-Dspring.main.allow-bean-definition-overriding=true
明天去试试。暂时先让服务启动起来。。。
没有用,设置了还是无法启动
■最终解决
Resin的Imart下面,的WEB-INF的Lib下面,
有一个多余的 AAA-main.jar
把上面这个多余的 jar 删掉, 就能正常启动了
====
■困惑和不解(含推测和补充说明)
①AAA-bb-main.jar
② AAA-main.jar
重复的Bean在①中,
即使我去掉了②、JVM启动时,①的jar也是被加载了。。。
# JVM 启动时,添加下面的参数,查看类的加载
-verbose:class
也就是说,下面这两个类,都被加载了
Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException:
Annotation-specified bean name 'xxxx' for bean class [aaa.bbb.ccc.gen.mapper.TTBean] conflicts with existing,
non-compatible bean definition of same name and class [aaa.bbb.ccc.mapper.TTBean]
神奇的是,去掉②之后,可以正常启动了,不再报上面的错误了。
【推测】继续调查
已经被JVM加载的类,什么时候被Spring容器加载
使用的时候加载。 难道使用了②, ①就会被Spring容器加载???
补充说明一下,
①和②都不是IMart制品原本的jar,而是现在要开发的这个Project相关の基盤のJar
====
■对应的java代码
===
public static void main(String[] args) {
SpringApplication app = new SpringApplication(MyApplication.class);
app.setAllowBeanDefinitionOverriding(true);
app.run(args);
}
■风险
隐患一:按类型注入(@Autowired)会直接启动失败
如果你的某个 Service 需要注入 com.a.User,但容器里最终保留的是 com.b.User(因为后者包扫描顺序靠后)。此时 Spring 会提示:
NoSuchBeanDefinitionException: No qualifying bean of type 'com.a.User' available
因为 com.a.User 已经被覆盖并移除了,启动虽然过了,但运行到注入这个 Bean 的地方就会报错。
隐患二:按名称注入(@Resource(name = "user"))会取错对象
即使注入成功,你拿到手的很可能是 com.b.User 的实例,但你的业务逻辑是按 com.a.User 来写的。数据类型可能不同,调用方法时极大概率会抛出 ClassCastException 或 NullPointerException,这种运行时的诡异错误比启动报错更难排查。
隐患三:MyBatis 层面的别名冲突依然存在
请再次注意:这个 JVM 参数只管 Spring 容器,完全不管 MyBatis 的 typeAliasesPackage 扫描!
如果 XML 里你没有写 FQDN(全限定名),MyBatis 注册别名时依然会因为两个 User 同名而抛出 TypeException。既然你之前说“按照方案一配置了”(在 XML 中用了 FQDN),这个风险才被排除。
更多推荐



所有评论(0)