Spring bean自定義命名策略(註解實現)

  我們都知道項目後台開發是從 控制層——業務層——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,重啟服務完美解決問題

    例如:

    

  其實技術不是太難,難的是遇到問題解決的過程,但是只有通過困難才能磨練自己,成長的道路上不僅要學會解決問題的技巧。還要學習掌握高級的技能,擴大自己的視野,一步一步實現自己的目標。