Spring无法自动装配存储库

时间:2015-08-18 08:41:25

标签: java xml spring spring-mvc

我遇到了Spring autowire的问题。我正在尝试使用Autowire来注入存储库,当我将它注入控制器时,它已经可用于身份验证服务。为了进一步参考,我正在添加相关代码和错误。

的web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <display-name>Restful Web Application</display-name>


     <context-param>
        <param-name>contextClass</param-name>
        <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
    </context-param>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            enterprise.util.SpringSecurityConfig
        </param-value>
    </context-param>

    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
    </filter-mapping>


    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>

    <servlet>
        <servlet-name>restEnterprise</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>restEnterprise</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>




</web-app>

restEnterpise-servlet.xml - EmployeeRepository位于dbService

<beans xmlns="http://www.springframework.org/schema/beans"

    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans    
        http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.0.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">

    <context:component-scan base-package="enterprise.service" />
    <context:component-scan base-package="enterprise.controller" />
    <context:component-scan base-package="enterprise.util" />
    <context:component-scan base-package="dbService" />

    <mvc:annotation-driven />

</beans>

SpringSecurityConfig.java

@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {

    private final TokenAuthenticationService tokenAuthenticationService; //handles adding auth token to response and checking for auth header in requests
    private final EmployeeDetailsService employeeDetailsService;
    public SpringSecurityConfig() {
        super(true);
        tokenAuthenticationService = new TokenAuthenticationService("tooManySecrets");
        employeeDetailsService = new EmployeeDetailsService();
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
      web
        .debug(true);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .exceptionHandling().and()
                .anonymous().and()
                .servletApi().and()
                .headers().cacheControl().and().and()
                .authorizeRequests()

                // Allow anonymous logins
                .antMatchers("/auth/**").permitAll()

                // All other request need to be authenticated
                .anyRequest().authenticated().and()

                // Custom Token based authentication based on the header previously given to the client
                .addFilterBefore(new StatelessAuthenticationFilter(tokenAuthenticationService), UsernamePasswordAuthenticationFilter.class);
    }

//http://docs.spring.io/spring-security/site/docs/current/apidocs/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurerAdapter.html

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService());
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Bean
    @Override
    public EmployeeDetailsService userDetailsService() { 
        return employeeDetailsService;
    }

//--------------

    @Bean
    public TokenAuthenticationService tokenAuthenticationService() {
        return tokenAuthenticationService;
    }
}

EmployeeDetailsS​​ervice.java

@Component
public class EmployeeDetailsService implements org.springframework.security.core.userdetails.UserDetailsService {

    @Autowired
    private EmployeeRepository employeeRep;

    @Override
    public final UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        Employee employee = employeeRep.findByLogin(username);
        if (employee == null) {
            throw new UsernameNotFoundException("Employee not found");
        }
        List<GrantedAuthority> authorities = buildUserAuthority(employee.getRole());
        return buildUserForAuthentication(employee, authorities);
    }

    // Converts Employee to
    // org.springframework.security.core.userdetails.User
    private User buildUserForAuthentication(Employee user, 
        List<GrantedAuthority> authorities) {
        return new User(user.getLogin(), user.getPassword(), 
            true, true, true, true, authorities);
    }

    private List<GrantedAuthority> buildUserAuthority(String userRole) {

        Set<GrantedAuthority> setAuths = new HashSet<GrantedAuthority>();

        setAuths.add(new SimpleGrantedAuthority("ROLE_" + userRole.toUpperCase()));

        List<GrantedAuthority> Result = new ArrayList<GrantedAuthority>(setAuths);

        return Result;
    }

}

部署期间出错

2015-08-18 10:15:34,389 ERROR [org.jboss.as.controller.management-operation]     (management-handler-thread - 1) JBAS014613: Operation ("redeploy") failed - address: ([("deployment" => "enterprise.war")]) - failure description: {"JBAS014671: Failed services" => {"jboss.undertow.deployment.default-server.default-host./enterprise" => "org.jboss.msc.service.StartException in service jboss.undertow.deployment.default-server.default-host./enterprise: Failed to start service
    Caused by: java.lang.RuntimeException: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'springSecurityFilterChain' defined in class org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.servlet.Filter]: Factory method 'springSecurityFilterChain' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userDetailsService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private dbService.dao.EmployeeRepository enterprise.service.EmployeeDetailsService.employeeRep; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [dbService.dao.EmployeeRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

正如我所说 - 当我在控制器中使用它而不在EmployeeDetailsS​​ervice中时,这个autowire可以工作。

3 个答案:

答案 0 :(得分:1)

不要使用new实例化EmployeeService,而应该让spring容器进行实例化和布线。

您可以将您的员工服务自动装配为

 @AutoWired
 private final EmployeeDetailsService employeeDetailsService;

并从构造函数中删除新的Instantiation,并从@Bean方法

中删除userDetailsService()注释

<强>已更新

如果你有一个主弹簧上下文xml将它导入配置类,如下所示

@Configuration
@ImportResource("restEnterpise-servlet.xml")
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter

如果您没有任何弹簧xml,您可以添加组件扫描注释以发现弹簧组件@ComponentScan

答案 1 :(得分:0)

如果您的存储库扩展JpaRepository,那么您需要在@Resource

中使用@Autowired代替EmployeeDetailsService

答案 2 :(得分:0)

This link will be helpfull

您的服务在restEnterpise-servlet.xml中声明,并且您想使用EmployeeRepository。但是在servlet配置之前加载了安全性配置。因此,您需要创建另一个spring配置,其中将声明所有组件扫描,并将在安全配置之前加载。 例如 spring-config.xml

 <beans xmlns="http://www.springframework.org/schema/beans"

    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans    
        http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.0.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">

    <context:component-scan base-package="enterprise.service" />
    <context:component-scan base-package="enterprise.controller" />
    <context:component-scan base-package="enterprise.util" />
    <context:component-scan base-package="dbService" />

    <mvc:annotation-driven />

</beans>

web.xml     

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/spring-config.xml
            enterprise.util.SpringSecurityConfig
        </param-value>
    </context-param>

我希望这会对你有所帮助。