Лучшие практики Spring Dependency Injection и вопросы аннотации @Autowired - PullRequest
0 голосов
/ 08 мая 2020

Я новый пользователь фреймворка Spring и не писал много кода для многопоточных корпоративных приложений java. Моя цель - написать службу REST с использованием Spring Boot 2, которая выполняет некоторые операции CRUD с базой данных. Я следил за предложениями многих веб-сайтов и смог написать (скопировать-вставить) код, который находится в рабочем состоянии.

Моя проблема в том, что я не уверен, будет ли мой код работать для нескольких параллельных запросов клиентов .

Ниже приведен фрагмент кода из моего приложения. Я игнорирую блоки try-catch et c. чтобы упростить сегмент кода.


//Controller Layer 
###############################
@RestController
public class MyController{

    @Autowired
    private MyService myService;   

    //Info object may contain a lot of fields, that's why I am using a post method instead of a get method
    @PostMapping(path = "/search", consumes = "application/json", produces = "application/json")
    public ResponseEntity<SearchDataResponse> search(@RequestBody Info info){

        SearchDataResponse searchDataResponse = myService.searchUser(info);
        return new ResponseEntity.ok(searchDataResponse);
    }
}
###############################

//Business Logic Layer 
###############################
@Service
public class MyService{

    @Autowired
    private MyRepository myRepository; 

    @Autowired
    private SearchDataResponse searchDataResponse; // I want to get a new SearchDataResponse automatically from Spring 

    @Autowired
    private Mapper mapper; //Using a custom mapper to map data from SearchDataDao object to a SearchDataResponse object

    public SearchDataResponse searchUser(Info info){

        //Fetch data from dao layer
        SearchDataDao searchDataDao = fetchUserInformationFromDatabase(info);

        //Map the data to a response object
        mapper.map(searchDataResponse, searchDataDao);

        //return the response to controller layer
        return searchDataResponse;
    }
}
###############################

// Data Access Layer 
###############################
@Repository
@Transactional
public class MyRepository{

    @Autowired
    private JdbcTemplate jdbcTemplate;

    public SearchDataDao fetchUserInformationFromDatabase(Info info) {

        // Assume I am using Spring JDBC template, database connection config classes are done correctly
        String query = "select * from user, address where age = ?";
        return jdbcTemplate.queryForObject(sql, new Object[]{info.getAge()}, new BeanPropertyRowMapper(SearchDataDao.class));
    }
}
###############################

// DTOs And DAOs
###############################
public class Info{
    private int age;
    private Address address
    //getters and setters
}

public class Address {
    private String street;
    //getters and setters
}
###############################


###############################
//prototype scope since I am assuming multiple requests will need multiple objects to store data
@Component(scope="prototype")
public class SearchDataResponse{    
    private String name;
    @Autowired
    private ExtraData extraData;
    //getters and setters and constructors
}

//prototype scope since I am assuming multiple requests will need multiple objects to store data
@Component(scope="prototype")
public class ExtraData{
    private String street;
    //getters and setters and constructors
}
###############################

###############################
publci class SearchDataDao{
    private int houseNumber;
    private String name;
    private String street;
    //getters and setters
}
###############################

###############################
// Mapper of SearchDataDao to SearchDataResponse 
@Component
public class Mapper {
    public void map(SearchDataResponse searchDataResponse, SearchDataDao searchDataDao){
        //map data here - using getters and setters
        searchDataResponse.setName(searchDataDao.getName());
        searchDataResponse.getExtraData.setStreet(searchDataDao.getStreet());
    }
}
###############################

Q1: Я читал, что аннотация @RestController создаст объект Singleton из класса MyController в контексте текущего приложения. Поэтому я предполагаю, что в приложении будет только один объект класса MyController. Итак, правильно ли, что несколько запросов от нескольких клиентов будут каким-то образом поставлены в очередь Spring Framework, прежде чем он сможет войти в объект MyController? Как это работает? Если есть очередь, где она?

Q2: Предположим, в настоящее время синглтон-объект MyController обрабатывает 2 запроса (я не знаю как). Сколько объектов типа Info class будет создано сервером приложений / Spring?

Q3: MyService класс также является одноэлементным классом, поскольку он имеет аннотацию @Service. Поэтому я предполагаю, что при запуске приложения Spring будет создан только один объект MyService. Почему данные из нескольких клиентских запросов не перекрываются внутри объекта myService? Я не видел ни одного веб-сайта, на котором этот аннотированный @Service класс MyService был бы компонентом области видимости прототипа.

Q4: Я создал класс SearchDataResponse с областью видимости прототипа. Но каким-то образом он хранит существующие данные. Я хочу получать новый объект SearchDataResponse для каждого запроса. Почему не работает? Я прочитал некоторую документацию по этому поводу, но все еще не очень ясно об этом.

Q5: Следуют ли приведенные выше сегменты кода стандартному / правильному способу разработки операций CRUD с использованием среды Spring?

Мы будем очень благодарны за любые предложения и рекомендации.

Спасибо.

1 Ответ

0 голосов
/ 08 мая 2020

Q1 / Q2 - сервлет является общим, но HttpServletRequest нет, вы можете прочитать больше здесь

Другие предложения: вы можете использовать Jmeter для тестирования многопоточных приложений, и вам не нужен Object из возврата метода Mapper, например Component, просто верните новый экземпляр из объекта, созданного в методе.

Надеюсь, я был вам полезен

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...