Reputation: 2906
I am new to Java/Spring Boot and am seeing unexpected functionality of a method that is overridden in a UserServiceImpl class. Even though this class is not exported, the overridden method is the one that is being used.
Basically, I have a UserService Interface class and a UserServiceImpl class for this interface. The UserService Interface has a createUser method declared. The UserServiceImpl then overrides this method and adds additional functionality.
The UserController class then imports the UserService Interface class and calls the createUser method. However, even though the UserServiceImpl is not imported into the UserController class, the overridden createUser method from this class is used. How is it possible for the UserController to know that the createUser method from the interface was overridden if the impl class in which it is overriden is not imported into the UserController?
I have included these classes below:
The UserService Interface:
package sbootproject.service.intrf;
import sbootproject.shared.dto.UserDto;
public interface UserService {
UserDto createUser(UserDto user);
}
The UserService Impl where the createUser method is overridden:
package sbootproject.service.impl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import sbootproject.UserRepository;
import sbootproject.entity.UserEntity;
import sbootproject.service.intrf.UserService;
import sbootproject.shared.dto.UserDto;
@Service
public class UserServiceImpl implements UserService {
@Autowired
UserRepository userRepository;
@Override
public UserDto createUser(UserDto user) {
UserEntity userEntity = new UserEntity();
BeanUtils.copyProperties(user, userEntity);
userEntity.setEncryptedPassword("test");
userEntity.setUserId("testUserId");
UserEntity storedUserDetails = userRepository.save(userEntity);
UserDto returnValue = new UserDto();
BeanUtils.copyProperties(storedUserDetails, returnValue);
return returnValue;
}
}
And finally, the UserController:
package sbootproject.controller;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import sbootproject.model.request.UserDetailsRequestModel;
import sbootproject.model.response.UserRest;
import sbootproject.service.intrf.UserService;
import sbootproject.shared.dto.UserDto;
@RestController
public class UserController {
@Autowired
UserService userService;
@PostMapping(path="/postMethod")
public UserRest createUser(@RequestBody UserDetailsRequestModel userDetails) {
UserRest returnValue = new UserRest();
UserDto userDto = new UserDto();
BeanUtils.copyProperties(userDetails, userDto);
UserDto createdUser = userService.createUser(userDto);
BeanUtils.copyProperties(createdUser, returnValue);
return returnValue;
}
}
Upvotes: 0
Views: 2269
Reputation: 40008
If there is only a single implementation of the interface and that is annotated with @Component or @service with Spring's component scan enabled, Spring framework can find out the (interface, implementation) pair.
@Qualifier
If you have more than one implementation, then you need @Qualifier annotation to inject the right implementation, along with @Autowired annotation.
Upvotes: 1
Reputation: 58774
Spring search for implementation of UserService
in context and find only one UserServiceImpl
, if you have 2 you will have an issue that could be fixed using profiles or Qualifier
Upvotes: 1