背景:
在使用 shiro-spring-boot-web-starter 时,启动项目报错。
Description:
Parameter 0 of method authorizationAttributeSourceAdvisor in org.apache.shiro.spring.boot.autoconfigure.ShiroAnnotationProcessorAutoConfiguration required a bean named ‘authorizer’ that could not be found.
Action:
Consider defining a bean named ‘authorizer’ in your configuration.
解读:
报错的意思是,在类 ShiroAnnotationProcessorAutoConfiguration中的这个方法的第0个参数,也就是securityManager ,缺少一个叫authorizer 的 Bean
因为依赖注入,这个方法需要参数securityManager,但是发现还没有这个Bean,于是进行实例化这个Bean,但是在实例化的时候,又依赖了一个叫 authorizer 的Bean,但发现无法实例化 authorizer ,于是报错。通过调试可以看到,报错具体在类AbstractShiroConfiguration中:
理论上说,authorizer 是 Shiro 中很重要的一个 Bean,用于登录认证,Springboot 肯定会帮我们注入的。查找一下,发现在ShiroWebAutoConfiguration这个类中,有自动注入。
事实上,因为有 @ConditionalOnMissingBean 注解,意思是如果已存在这个类型的 Bean ,就不执行本方法。这个方法没有得到真正的执行。
实际上这个时候如果你对Spring的 Bean加载很熟悉的话,完全可以debug进去,看看为什么会出现已经有这个类型的 Bean 了。非常详细,参见:
https://blog.youkuaiyun.com/weixin_34289454/article/details/94562045
结论就是,因为你自定义的 Realm 间接地实现了 Authorizer 接口,所以它是 Authorizer 类型的 Bean。所以刚才那里,@ConditionalOnMissingBean 会查到,已经有这个类型的 Bean了,不再注入了。
但问题是,为什么刚才打断点的地方:
securityManager.setAuthorizer(authorizer());
中的 authorizer() 方法不执行?实际上是因为Spring的代理类去执行,会找名为 authorizer 的 Bean,发现没有,才报错。
解决办法
知道了原因,就知道如何解决了
方法一: 手动注入这个Bean
@Configuration
public class ShiroConfig {
@Bean
public Authorizer authorizer(){
return new ModularRealmAuthorizer();
}
}
方法二: 不用Springboot 自动注入的sercurityManager 了,我自己在 ShiroConfig 中 注入。
方法三:
我把自己写的 Realm 的 Bean 名字定为"authorizer"