Dog
Dog

Reputation: 2906

How spring @autowired works for interface and implementation classes

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

Answers (2)

Ryuzaki L
Ryuzaki L

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

Ori Marko
Ori Marko

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

Related Questions