Java?SpringBoot整合shiro-spring-boot-starterqi項(xiàng)目報(bào)錯(cuò)解決
1、項(xiàng)目啟動(dòng)時(shí)報(bào)錯(cuò)如下
Description: The bean 'securityManager', defined in class path resource [org/apache/shiro/spring/config/web/autoconfigure/ShiroWebAutoConfiguration.class], could not be registered. A bean with that name has already been defined in class path resource [com/ncwu/common/infrastructure/config/ShiroConfig.class] and overriding is disabled. Action: Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true
2、原因分析
我的自定義ShiroConfig配置類中添加的安全管理器,
代碼如下:
@Bean public SecurityManager securityManager(JwtRealm jwtRealm) { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); //配置realm securityManager.setRealm(jwtRealm); return securityManager; }
根據(jù)異常信息查看ShiroWebAutoConfiguration源碼時(shí)發(fā)現(xiàn)其中已經(jīng)定義了securityManager方法,我們?cè)赟hiroConfig配置類中再次定義securityManager方法,因返回的類與其不一樣導(dǎo)致出錯(cuò),
ShiroWebAutoConfiguration類中定義的securityManager方法代碼如下:
@Bean @ConditionalOnMissingBean @Override protected SessionsSecurityManager securityManager(List<Realm> realms) { return super.securityManager(realms); }
下面這些為補(bǔ)充知識(shí):我們都知道@ConditionalOnBean作用是根據(jù)value屬性按bean的類型或則bean的名稱判斷bean是否在IOC容器中,如果在就返回true,否則返回false。而@ConditionalOnMissingBean的作用與@ConditionalOnBean相反。如果@ConditionalOnBean和@ConditionalOnMissingBean這兩個(gè)注解沒(méi)有參數(shù),那這兩個(gè)注解以何種方式來(lái)判斷呢?在Spring Boot官方文檔中找出了答案。
意思是:在@ConditionalOnMissingBean沒(méi)有參數(shù)的情況下,目標(biāo)類型默認(rèn)為方法的返回類型,如果IOC容器中沒(méi)有類型為MyService及其子類的Bean,那么myServiceBean將被創(chuàng)建。
從源代碼中可以看出@ConditionalOnMissingBean沒(méi)有參數(shù),那么如果IOC容器中沒(méi)有類型為SessionsSecurityManager及其子類的Bean,那么該方法則會(huì)執(zhí)行,并且源碼securityManager方法返回的是SessionsSecurityManager,而自己定義的ShiroConfig中返回的是SecurityManager(因?yàn)锧Bean注解會(huì)指定改bean的類型為該方法的返回類型),所以它會(huì)判斷出IOC容器中沒(méi)有類型為SessionsSecurityManager及其子類的Bean,源碼中的方法執(zhí)行,故IOC容器中有兩個(gè)名為securityManager的Bean,因而報(bào)錯(cuò)。所以如果要自定義securityManager方法,返回類型只能是SessionsSecurityManager及其子類,而SessionsSecurityManager的子類是DefaultSecurityManager,DefaultWebSecurityManager又繼承DefaultSecurityManager,
相關(guān)類圖如下:
故而正確的代碼應(yīng)該是:
@Bean public SessionsSecurityManager securityManager(JwtRealm jwtRealm) { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); //配置realm securityManager.setRealm(jwtRealm); return securityManager; } //或者如下,將方法返回類型改為DefaultWebSecurityManager /*@Bean public DefaultWebSecurityManager securityManager(JwtRealm jwtRealm) { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); //配置realm securityManager.setRealm(jwtRealm); return securityManager; }*/
3、測(cè)試@ConditionalOnMissingBean注解
新建下面3個(gè)類:
//動(dòng)物 @Data public class Animal { private String name; private Integer age; } //狗 @EqualsAndHashCode(callSuper = true) @Data public class Dog extends Animal { private String type; } //二哈 @EqualsAndHashCode(callSuper = true) @Data public class TwoHa extends Dog { private String a; }
啟動(dòng)類:
@SpringBootApplication //掃描下面的接口生成代理實(shí)現(xiàn)類 @MapperScan("com.ncwu.**.domain.mapper") public class ShiroApplication { public static void main(String[] args) { SpringApplication.run(ShiroApplication.class, args); } //若IOC容器中沒(méi)有Animal類型及其子類Dog類型的bean時(shí),該方法才會(huì)執(zhí)行 @Bean @ConditionalOnMissingBean public Animal twoHa(JwtRealm realm) { TwoHa twoHa = new TwoHa(); twoHa.setType("twoHa1"); twoHa.setAge(10); twoHa.setName("twoHa1"); return twoHa; } @Bean public Dog twoHa() { TwoHa twoHa = new TwoHa(); twoHa.setType("twoHa2"); twoHa.setAge(20); twoHa.setName("twoHa2"); return twoHa; } }
測(cè)試類:
@RunWith(SpringRunner.class) @SpringBootTest(classes = ShiroApplication.class) public class TestDao { @Autowired private ApplicationContext appContext; @Test public void test() throws Exception{ /*String[] beanNamesForType = appContext.getBeanNamesForType(Animal.class); for (String s : beanNamesForType) { System.out.println(s); }*/ appContext.getBean(Animal.class); //appContext.getBean("dog"); } }
測(cè)試結(jié)果:
到此這篇關(guān)于Java SpringBoot整合shiro-spring-boot-starterqi項(xiàng)目報(bào)錯(cuò)解決的文章就介紹到這了,更多相關(guān)Java SpringBoot 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring?Boot在Web應(yīng)用中基于JdbcRealm安全驗(yàn)證過(guò)程
這篇文章主要為大家介紹了Spring?Boot在Web應(yīng)用中基于JdbcRealm安全驗(yàn)證過(guò)程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪<BR>2023-02-02關(guān)于shiro中部分SpringCache失效問(wèn)題的解決方法
這篇文章主要給大家介紹了關(guān)于shiro中部分SpringCache失效問(wèn)題的解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-07-07Java web實(shí)現(xiàn)賬號(hào)單一登錄,防止同一賬號(hào)重復(fù)登錄(踢人效果)
這篇文章主要介紹了Java web實(shí)現(xiàn)賬號(hào)單一登錄,防止同一賬號(hào)重復(fù)登錄,有點(diǎn)類似于qq登錄踢人效果,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-10-10springboot工程jar包部署到云服務(wù)器的方法
這篇文章主要介紹了springboot工程jar包部署到云服務(wù)器的方法,本文通過(guò)實(shí)例介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2018-05-05Java橋梁設(shè)計(jì)模式優(yōu)雅地將抽象與實(shí)現(xiàn)分離
Java橋接設(shè)計(jì)模式通過(guò)將抽象和實(shí)現(xiàn)分離,使得它們可以獨(dú)立地變化,從而實(shí)現(xiàn)更靈活的代碼結(jié)構(gòu)。它是一種優(yōu)雅的設(shè)計(jì)模式,適用于需要處理多個(gè)變化因素的復(fù)雜應(yīng)用程序2023-04-04