简体   繁体   中英

Autowired bean is null

I have read a lot of questions about autowiring on Stackoverflow but I still cannot figure why my autowiring does not work.

I have a standard directory structure :

com.mycompany
  |-controller
  |-service
  |-model

When I inject Services from Controllers, everything works fine. But when I try to give a custom implementation of UserDetailService to spring security, it fails:

@Service
public class MyCustomUserDetailService implements UserDetailsService {

  @Autowired
  private UserService userService; //This attribute remains null

  @Override
  public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
    try {
      User userByEmail = userService.findUserByEmail(email); //NullPointerException
      return new UserDetailsAdapter(userByEmail);
    } catch(NoResultException e) {
      return null;
    }
  }
}

UserService is a very simple Service, anotated with @Service :

import org.springframework.stereotype.Service;

@Service
public class UserService {
  [...]
}

Note : UserService is correctly autowired when instantiated from UserController :

@RestController
@RequestMapping("/user")
public class UserController {

  @Autowired
  private UserService service; //This one works!

Here is the dispatcher-servlet.xml (see the component-scan) :

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

  <context:component-scan base-package="com.mycompany"/>
  <tx:annotation-driven/>
  <mvc:annotation-driven/>
</beans>

And here is the relevant part of the Spring context :

<beans:bean id="customUserDetailService" class="com.mycompany.service.customUserDetailService"/>

<authentication-manager>
  <authentication-provider user-service-ref="customUserDetailService">
  </authentication-provider>
</authentication-manager>

Any idea?

I'm pretty sure that your problem is related to the fact that the your bean is managed by the DispatcherServlet context instead of the root context. By putting the <context:component-scan base-package="com.mycompany"/> in the DispatcherServlet context, all the beans scanned on these packages would be managed by the DispatcherServlet context and are not visible by the root context which is the one that manage your MyCustomUserDetailService bean.

The DispatcherServlet is a child of the root context and that allows your core beans from the root context to be injected into the view-layer beans like controllers. The visibility is only one way, you can't inject beans from the DispatcherServlet context into a bean manage by the root context, that's why it works in the UserController but not in the MyCustomUserDetailService .

Moving the <context:component-scan base-package="com.mycompany"/> tag to the root context (Spring context) should do the trick.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM