2015-08-18 56 views
0

我遇到Spring autowire問題。我正在嘗試使用Autowire來注入存儲庫,這在注入控制器的過程中已經適用於身份驗證服務。爲了進一步的參考,我添加了相關的代碼和錯誤。Spring未能自動裝入資源庫

的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

部署

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)} 

正如我已經說過期間

@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; 
    } 

} 

錯誤 - 當我使用它的控制器,但不是在這個EmployeeDetailsS​​ervice自動裝配工作。

+0

哪裏是它實現/類擴展'dbService.dao.EmployeeRepository'? – Aakash

+0

是否將'dbService.dao.EmployeeRepository'註釋爲存儲庫? – Jens

+0

爲什麼你使用new來實例化EmployeeDetailsS​​ervice。?使用new在spring容器外創建實例 – jozzy

回答

1

而不是實例化使用新的EmployeeService,你應該讓spring容器做實例化和佈線。

可以自動裝配你的EmployeeService作爲

@AutoWired 
private final EmployeeDetailsService employeeDetailsService; 

,並從構造函數刪除新的實例化,也從userDetailsService()方法

修訂版刪除@Bean註釋

如果你有一個主彈簧context xml將其導入到配置類中,如下所示

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

如果你沒有任何的Spring XML的,您可以添加註釋componentscan發現彈簧組件@ComponentScan

+0

當我做你的修復,我得到錯誤上下文初始化失敗:org.springframework.beans.factory.BeanCreationException:創建名爲'springSecurityConfig'的bean時出錯:注入自動裝配依賴失敗; (...)無法自動裝入字段:private enterprise.service.EmployeeDetailsS​​ervice enterprise.util.SpringSecurityConfig.employeeDetailsS​​ervice;(...)找不到符合條件的[enterprise.service.EmployeeDetailsS​​ervice]類型的限定bean:(...) 「看起來G.克魯巴赫是對的。這是加載內容的問題。 –

+0

非常感謝!您的更新和原始帖子幫助我解決了這個問題 –

0

如果你的版本庫擴展JpaRepository,那麼你需要在你的EmployeeDetailsService

+0

存儲庫擴展CRUDRepository –

0

This link will be helpfull使用@Resource代替@Autowired

您的服務在restEnterpise-servlet.xml中聲明,並且您想要使用EmployeeRepository。但是在您的servlet配置之前加載安全配置。因此,您需要創建另一個彈簧配置,其中將聲明所有組件掃描並將在安全配置之前加載。 例如 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> 

我希望這會幫助你。

+0

是的,可以。問題是,當我使用你的解決方案時,我得到了 '2015-08-18 12:06:49,467 INFO [org.springframework.web.context.support.AnnotationConfigWebApplicationContext](MSC服務線程1-1)找不到註釋類用於指定的類/包[/ WEB-INF/spring-beforeSecurityLoad.xml'。你知道它爲什麼找不到任何東西嗎? –

+0

'spring-beforeSecurityLoad.xml'中的內容是什麼?嘗試閱讀本[後](http://stackoverflow.com/questions/8075790/how-to-register-spring-configuration-annotated-class-instead-of-applicationcont)。 –

+0

我只是從servlet配置文件複製和粘貼組件掃描。 –