使用Spring Boot集成Shiro时出现了无法注入Service的问题

简介: 使用Spring Boot集成Shiro时出现了无法注入Service的问题

问题现象:

在ShiroRealm中进行身份验证,要将登陆模块的Service注入进来进行验证,但是其值为null。

public class ShiroRealm extends AuthorizingRealm {
    @Autowired
    ILoginService loginService; // <---这里值为null
    ...
}

问题原因:

  • ShiroRelam属于filter即过滤器,它在Spring未完成注入bean之前就已经拦截了,因此无法注入。
  • 对于SpringBoot,没有将ShiroRealm注入Bean。

Spring MVC 解决办法:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
    ...
    <!-- Spring MVC 前端控制器 -->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring/springmvc.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
  ...
    <!-- Shiro拦截器 -->
    <filter>
        <filter-name>shiroFilter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        <init-param>
            <param-name>targetFilterLifecycle</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>shiroFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    ...
</web-app>

Spring Boot 解决办法:

ShiroConfig在注入SecurityManager时setRealm()的参数ShiroRealm不能自己new出来,而要先将其注入Bean,然后调用(这里是个坑,很多人其实挂在这一步)。

错误写法:

@Configuration
public class ShiroConfig {
    ...
    @Bean
    public SecurityManager securityManager() {
        DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
        manager.setRealm(new shiroRealm());
        return manager;
    }
    ...
}

正确写法:

@Configuration
public class ShiroConfig {
    ...
    /**
     * 注入ShiroRealm 
     * 不能省略,会导致Service无法注入
     */
    @Bean
    public ShiroRealm myShiroRealm() {
        return new ShiroRealm();
    }
    @Bean
    public SecurityManager securityManager() {
        DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
        manager.setRealm(myShiroRealm());
        return manager;
    }
    ...
}

最强解决办法

如果上面的方法使用后还是不能注入Service,那么试试下面这样做(这种方法适用于在普通类中注入Service层):

创建一个SpringBeanFactoryUtils,用于获取Bean,记得添加@Component注解:

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class SpringBeanFactoryUtils implements ApplicationContextAware {
    private static ApplicationContext context = null;
    public static <T> T getBean(Class<T> type) {
        return context.getBean(type);
    }
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if (SpringBeanFactoryUtils.context == null) {
            SpringBeanFactoryUtils.context = applicationContext;
        }
    }
}

后面使用的时候,使用getBean()方法即可:

if (loginService == null) {
  loginService = SpringBeanFactoryUtils.getBean(ILoginService.class);
}


相关文章
|
1月前
|
XML Java 开发者
Spring Boot中的bean注入方式和原理
Spring Boot中的bean注入方式和原理
63 0
|
19天前
|
Java 测试技术
SpringBoot整合单元测试&&关于SpringBoot单元测试找不到Mapper和Service报java.lang.NullPointerException的错误
SpringBoot整合单元测试&&关于SpringBoot单元测试找不到Mapper和Service报java.lang.NullPointerException的错误
21 0
|
1天前
|
SQL Java 数据库连接
Spring脚手架集成分页插件
Spring脚手架集成分页插件
6 0
|
1天前
|
Java Spring
Spring Boot脚手架集成校验框架
Spring Boot脚手架集成校验框架
6 0
|
3天前
|
Java Spring 容器
Spring注入
Spring注入
24 13
|
8天前
|
Java Spring 容器
SpringBoot 使用Quartz执行定时任务对象时无法注入Bean问题
SpringBoot 使用Quartz执行定时任务对象时无法注入Bean问题
11 1
|
15天前
|
JSON Java 数据库连接
属性注入掌握:Spring Boot配置属性的高级技巧与最佳实践
属性注入掌握:Spring Boot配置属性的高级技巧与最佳实践
23 1
|
1月前
|
Java 数据库连接 数据库
Spring Boot整合MyBatis Plus集成多数据源轻松实现数据读写分离
Spring Boot整合MyBatis Plus集成多数据源轻松实现数据读写分离
26 2
|
1月前
|
监控 NoSQL Java
Spring Boot集成Redis启动失败【Caused by: java.lang.ClassNotFoundException: org.apache.commons.pool2.impl.G】
Spring Boot集成Redis启动失败【Caused by: java.lang.ClassNotFoundException: org.apache.commons.pool2.impl.G】
|
1月前
|
存储 NoSQL Java
如何使用Spring Boot与Redis集成
2月更文挑战第12天】
54 0

热门文章

最新文章