Spring:autowired DAO在自定义UserServiceDetails实现中为null

时间:2016-11-01 10:08:39

标签: spring spring-security autowired

我在Spring项目中配置安全性,不幸的是我遇到了问题。为什么CustomUserDetailsS​​ervice.java中的自动连接userDAO为空?

以下是相关代码:

CustomUserDetailsS​​ervice.java

@Service("customUserDetailsService")
@ComponentScan(basePackages="...")
public class CustomUserDetailsService implements UserDetailsService {

   @Autowired
   private UserDAO userDAO;

   public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

       // userDAO is null
       UserModel user = userDAO.getUserByUsername(username);
       ...
   }
}

弹簧security.xml文件

<beans:beans xmlns="http://www.springframework.org/schema/security"
   xmlns:beans="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
   http://www.springframework.org/schema/security
   http://www.springframework.org/schema/security/spring-security-3.2.xsd">

<http pattern="/resources/**" security="none"/>
<http pattern="/login" security="none"/>

<http auto-config="true">
    <intercept-url pattern="/**" access="ROLE_USER" />
    <form-login
        login-page="/login"
        default-target-url="/home"
        authentication-failure-url="/login?error"
        username-parameter="username"
        password-parameter="password" />
    <logout logout-success-url="/login?logout" />
</http>

<authentication-manager>
    <authentication-provider user-service-ref="customUserDetailsService">
        <password-encoder ref="encoder" />
    </authentication-provider>
</authentication-manager>

<beans:bean id="encoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder">
    <beans:constructor-arg name="strength" value="10" />
</beans:bean>

<beans:bean id="customUserDetailsService" class="... .service.CustomUserDetailsService" />

编辑:

UserDAOImpl.java

public class UserDAOImpl implements UserDAO {

private JdbcTemplate jdbcTemplate;

public UserDAOImpl(DataSource dataSource) {
    jdbcTemplate = new JdbcTemplate(dataSource);
}

   public UserModel getUserByUsername(String username) {

       String sql = "SELECT * FROM users WHERE username = '" + username + "'";

       return jdbcTemplate.query(sql, new ResultSetExtractor<UserModel>() {

            public UserModel extractData(ResultSet rs) throws SQLException, DataAccessException {
               if (rs.next()) {
                   UserModel user = new UserModel();
                   user.setUsername(rs.getString("username"));
                   user.setPassword(rs.getString("passwort"));
                   user.setEnabled(rs.getBoolean("enabled"));

                   return user;
               }
               return null;
           }
       });
   }
}

以下是基于Java的配置文件中的代码段:

@Bean
public UserDAO getUserDAO() {
    return new UserDAOImpl(getDataSource());
}

有趣的是,这种配置似乎有点工作。当我将UserDAO自动装入我的控制器时,它完全正常:

MainController.java

@RequestMapping(value = {"", "/", "/home"})
public String homeHandler(Model model) {

    // userDAO is not null, works perfectly fine and returns the UserModel-Object as expected
    UserModel user = userDAO.getUserByUsername("dx");

    ...
}

我已经阅读了一些Q&amp; A,但到目前为止,它涉及自定义UserDetailsS​​ervice的手动实例化。我的代码出了什么问题?

2 个答案:

答案 0 :(得分:1)

问题似乎是因为您在两个不同的地方实例化customUserDetailsService。您在spring-security.xml文件中有<bean>的定义,并且您在类本身上有@Service注释。在XML bean定义中,您没有注入UserDAO以使其为空。

您需要简化项目以清除java配置或XML文件中的bean定义(这不是必需的,您可以使用XML + java配置,但这会使实例化哪个bean变得非常混乱)。你没有多少选择;

  1. 删除CustomUserDetailsService的XML声明。在XML中添加<context:component-scan>并添加包名称,并从@ComponentScan中删除CustomUserDetailsService。这将允许spring扫描包并注册标有@Service@Bean等注释的bean。确保您的java配置类标有@Configuration注释。

  2. 您可以决定对所有bean使用XML配置,在这种情况下,您需要删除@Bean@Service等注释并在spring XML bean定义中声明所有这些注释并确保每个都注入了适当的依赖项。

  3. 您肯定需要清理bean定义,以便注入正确的依赖项。

答案 1 :(得分:0)

感谢您的回复。 Setu的回答是最有帮助的。显然,问题确实是双重实例化。我添加了<context:component-scan base-package="... .service" />并在@Service("customUserDetailsService")中留下了注释@ComponentScan(basePackages="...")CustomUserDetailsService(没有@ComponentScan它没有工作)。