Ответ
Все три аннотации являются специализациями @Component и регистрируют класс как bean в контексте Spring. Их основное различие — семантическое, для обозначения слоя архитектуры приложения и включения специфического поведения.
| Аннотация | Слой | Назначение и особенности |
|---|---|---|
@Repository |
Слой доступа к данным (DAO) | 1. Помечает класс как репозиторий. 2. Автоматически транслирует исключения конкретных поставщиков данных (например, JDBC SQLException) в непроверяемые исключения Spring DataAccessException. |
@Service |
Слой бизнес-логики | 1. Помечает класс как сервис, содержащий бизнес-логику. 2. Не имеет дополнительной технической функциональности по умолчанию, но используется для четкого разделения ответственности. Часто является точкой для применения транзакций (@Transactional). |
@Controller |
Слой представления (веб) | 1. Помечает класс как контроллер Spring MVC. 2. Позволяет автоматическое обнаружение методов, обрабатывающих HTTP-запросы (в сочетании с @RequestMapping и др.). 3. Используется для возврата представлений (View). @RestController — это специализация для REST API, которая добавляет @ResponseBody на уровне класса. |
Примеры:
// Слой данных
@Repository
public class JpaUserRepository implements UserRepository {
@PersistenceContext
private EntityManager em;
// ... методы доступа к данным
}
// Слой бизнес-логики
@Service
public class UserService {
@Transactional
public User createUser(UserDto dto) { ... }
}
// Веб-слой
@Controller
@RequestMapping("/users")
public class UserController {
@GetMapping
public String listUsers(Model model) { ... }
}
Использование правильных стереотипных аннотаций улучшает читаемость кода и позволяет Spring применять к ним специфические аспекты.
Ответ 18+ 🔞
Давай разберём эту троицу, а то у новичков иногда мозг вскипает, как чайник забытый. Все эти штуки — @Repository, @Service, @Controller — они, по сути, все под капотом @Component. Spring их видит и говорит: «Ага, вот ещё один боб на моей грядке, сейчас я его в контекст запихну».
Но зачем тогда три разных, если можно везде @Component тыкать? А затем, сука, чтобы не быть распиздяем! Это как маркировка: видишь аннотацию — сразу понимаешь, что этот класс делает и в каком слое архитектуры он сидит. Плюс, Spring для некоторых из них включает дополнительные плюшки.
@Repository — это тот самый чувак, который к базе лезет.
Его главная фишка — перевод исключений. Без него, если из недр JDBC вылезет какая-нибудь SQLException, тебе придётся её самому ловить и обрабатывать. А @Repository делает это автоматически: оборачивает все эти техногенные SQLException, JPAException и прочую хуйню в красивые, непроверяемые исключения Spring DataAccessException. Красота! Писал себе репозиторий и не парился.
@Service — это мозги операции, слой бизнес-логики.
По технической части — да, почти то же самое, что @Component. Но семантика, блядь! Видишь @Service — понимаешь, что тут живут твои основные правила, расчёты и прочая магия приложения. Это точка, где обычно вешают @Transactional, чтобы всё либо выполнилось, либо откатилось. Чёткое разделение, никакой ерунды.
@Controller — это лицо для веба.
Его Spring MVC специально ищет, чтобы понять, какой метод какой HTTP-запрос обрабатывает. Без него @RequestMapping просто так не заведётся. Он заточен под возврат представлений (View). А если тебе REST API пишешь, то есть его брат-близнец — @RestController. Это тот же @Controller, но он по умолчанию ко всем методам @ResponseBody прикручивает, чтобы не писать его каждый раз. Удобно, ёпта!
Вот тебе живые примеры, чтобы вообще всё стало ясно:
// Этот парень работает с базой. @Repository — его метка.
@Repository
public class JpaUserRepository implements UserRepository {
@PersistenceContext
private EntityManager em;
// ... тут он данные таскает, как заправский грузчик
}
// А это уже наш сервис, голова. Вся бизнес-логика тут.
@Service
public class UserService {
@Autowired
private UserRepository repository;
@Transactional // Чтоб всё адекватно коммитилось или откатывалось
public User createUser(UserDto dto) {
// ... тут какая-то хитрая проверка и логика перед сохранением
return repository.save(new User(dto));
}
}
// Ну а этот красавец общается с внешним миром через HTTP.
@Controller
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService service;
@GetMapping
public String listUsers(Model model) {
model.addAttribute("users", service.getAllUsers());
return "users/list"; // И говорит, какую вёрстку показывать
}
}
Короче, используй их по назначению. Код станет чище, архитектура понятнее, а другие разработчики (и ты сам через полгода) не будут материться, пытаясь разобраться, что тут за хуйня происходит. Это ж элементарно, Ватсон!