Spring bean自定義命名策略(註解實現)
- 2020 年 8 月 4 日
- 筆記
我們都知道項目後台開發是從 控制層——業務層——mybatis層,@Controller、@Service、@Mapper…等等註解可以將對象自動載入到bean容器中,還能實現相應的功能,使用起來得心應手。並且模組化實現解耦合,套用模板增刪改查等功能很快就寫出來。
那有沒有想過一個問題,如果在不同模組中有相同名稱的類,那註解將對象自動載入到bean容器中的名稱是默認的類名稱,會不會有重名的問題?會不會程式啟動報錯?答案當然會。
例如:
Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'imageController' for bean class [io.renren.modules.swr.controller.ImageController] conflicts with existing, non-compatible bean definition of same name and class [io.renren.modules.db.controller.ImageController] at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.checkCandidate(ClassPathBeanDefinitionScanner.java:349) at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:287) at org.springframework.context.annotation.ComponentScanAnnotationParser.parse(ComponentScanAnnotationParser.java:132) at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:295) at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:249) at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:206) at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:174) ... 13 common frames omitted
利用翻譯軟體翻譯一下:為bean類[io.renren.modules.swr.controller.ImageController]指定的註解bean名稱「imageController」與同名類[io.renren.modules.db.controller.ImageController]的現有的、不兼容的bean定義衝突。即,存在兩個imageController,導致bean衝突。
大致知道原因了,怎麼解決呢?以下有兩種解決方案
-
修改重複的類名稱
這相當於廢話…也感覺很雞肋,難道沒有自定義bean的命名策略嗎?肯定有的,請看以下方案
-
自定義bean命名策略
@Controller——>@Controller(“dbImageController”),可以傳入一個String類型的參數(只要不重名叫什麼都行,不寫默認是小寫開頭的類名稱),表示將bean名稱重命名為dbImageController
例如:
@Service——>@Service(“dbImageServiceImpl”),可以傳入一個String類型的參數,表示將bean名稱重命名為dbImageServiceImpl
例如:
@Mapper,由於@Mapper不支援傳入參數,但是我們可以寫個自定義注入的註解@Component(“dbImageDao”),表示將bean名稱重命名為dbImageDao,等同於@Repository(“dbImageDao”)
例如:
ok,現在啟動程式,如果你要是使用了基礎實體類(繼承BaseEntity)的話,你又會發現報錯
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.apache.ibatis.session.SqlSessionFactory]: Factory method 'sqlSessionFactory' threw exception; nested exception is org.apache.ibatis.type.TypeException: The alias 'ImageEntity' is already mapped to the value 'io.renren.modules.swr.entity.ImageEntity'. at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185) at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:651) ... 56 common frames omitted Caused by: org.apache.ibatis.type.TypeException: The alias 'ImageEntity' is already mapped to the value 'io.renren.modules.swr.entity.ImageEntity'. at org.apache.ibatis.type.TypeAliasRegistry.registerAlias(TypeAliasRegistry.java:157) at org.apache.ibatis.type.TypeAliasRegistry.registerAlias(TypeAliasRegistry.java:147) at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184) at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175) at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175) at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175) at java.util.HashMap$KeySpliterator.forEachRemaining(HashMap.java:1553) at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481) at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471) at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151) at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174) at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418) at com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean.buildSqlSessionFactory(MybatisSqlSessionFactoryBean.java:517) at com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean.afterPropertiesSet(MybatisSqlSessionFactoryBean.java:430) at com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean.getObject(MybatisSqlSessionFactoryBean.java:628) at com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration.sqlSessionFactory(MybatisPlusAutoConfiguration.java:214) at com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration$$EnhancerBySpringCGLIB$$1cfc4994.CGLIB$sqlSessionFactory$1(<generated>) at com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration$$EnhancerBySpringCGLIB$$1cfc4994$$FastClassBySpringCGLIB$$641672b3.invoke(<generated>) at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244) at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331) at com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration$$EnhancerBySpringCGLIB$$1cfc4994.sqlSessionFactory(<generated>) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ... 57 common frames omitted
報錯資訊的翻譯是:別名’ImageEntity’已映射到’io.renren.modules.swr.entity.ImageEntity’.
同樣的我們加個註解,@Alias(“dbImageEntity”),表示將實體名稱重命名為dbImageEntity,重啟服務完美解決問題
例如:
其實技術不是太難,難的是遇到問題解決的過程,但是只有通過困難才能磨練自己,成長的道路上不僅要學會解決問題的技巧。還要學習掌握高級的技能,擴大自己的視野,一步一步實現自己的目標。