← Назад к вопросам

В чем разница между @Component, @Service и @Repository?

1.0 Junior🔥 301 комментариев
#Spring Framework#Основы Java

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

В чем разница между @Component, @Service и @Repository

Все три аннотации в Spring — это стереотипы для автоматической регистрации компонентов в IoC контейнере, но они используются для разных целей и имеют некоторые отличия.

Иерархия аннотаций

@Component
    |
    ├─→ @Service
    ├─→ @Repository
    └─→ @Controller/@RestController

Все они наследуются от @Component, но имеют разные семантические значения и дополнительную функциональность.

1. @Component — базовая аннотация

Это самая общая аннотация для регистрации bean'а в контейнере.

@Component
public class EmailNotificationService {
    public void sendEmail(String email, String message) {
        System.out.println("Отправляю: " + message);
    }
}

Когда использовать:

  • Вспомогательные служебные классы
  • Конвертеры, валидаторы
  • Утилиты, которые не подходят под другие категории
  • Если вы не уверены, какой использовать

Особенности:

  • Просто регистрирует класс как bean
  • Нет специальной обработки

2. @Service — для бизнес-логики

Это аннотация для сервисного слоя, где находится бизнес-логика приложения.

@Service
public class OrderService {
    
    @Autowired
    private OrderRepository orderRepository;
    
    @Autowired
    private PaymentService paymentService;
    
    @Transactional
    public void createOrder(OrderRequest request) {
        // Бизнес-логика: валидация, расчёты, сохранение
        Order order = new Order();
        order.setTotal(calculateTotal(request.getItems()));
        
        orderRepository.save(order);
        paymentService.processPayment(order);
    }
    
    private BigDecimal calculateTotal(List<Item> items) {
        return items.stream()
            .map(Item::getPrice)
            .reduce(BigDecimal.ZERO, BigDecimal::add);
    }
}

Когда использовать:

  • Сервисы с бизнес-логикой
  • Транзакционные операции
  • Оркестрация между репозиториями и другими сервисами
  • Основная логика приложения

Особенности:

  • Семантически ясно, что это бизнес-логика
  • По умолчанию перехватывает исключения
  • Работает хорошо с @Transactional

3. @Repository — для доступа к данным

Это аннотация для слоя доступа к данным (Data Access Layer).

@Repository
public class OrderRepository {
    
    @Autowired
    private EntityManager entityManager;
    
    public void save(Order order) {
        entityManager.persist(order);
    }
    
    public Order findById(Long id) {
        return entityManager.find(Order.class, id);
    }
    
    public List<Order> findAllByStatus(String status) {
        return entityManager.createQuery(
            "SELECT o FROM Order o WHERE o.status = :status",
            Order.class
        )
        .setParameter("status", status)
        .getResultList();
    }
}

Когда использовать:

  • Классы для работы с БД
  • Data Access Objects (DAO)
  • Вместо JpaRepository (если пишешь свои запросы)

Особенности:

  • PersistenceExceptionTranslator — преобразует исключения БД в Spring исключения
  • Spring автоматически преобразует SQLException в DataAccessException
  • Специальная обработка исключений БД

Важная разница: Обработка исключений

// @Repository имеет специальный обработчик для исключений БД
@Repository
public class BadRepository {
    @Autowired
    private JdbcTemplate jdbc;
    
    public User findUser(String sql) {
        try {
            return jdbc.queryForObject(sql, User.class);
        } catch (SQLException e) {
            // ❌ SQLException будет автоматически обёрнута в DataAccessException
            throw new DataAccessException("DB Error", e) {
            };
        }
    }
}

// @Service не имеет этой обработки
@Service
public class MyService {
    public void process() {
        // SQLException здесь пройдёт как есть
        // (если только не обработаешь явно)
    }
}

Практическое применение: Слоистая архитектура

// Слой Presentation (контроллер)
@RestController
@RequestMapping("/api/orders")
public class OrderController {
    
    @Autowired
    private OrderService orderService; // @Service
    
    @PostMapping
    public ResponseEntity<OrderDTO> createOrder(@RequestBody OrderRequest req) {
        Order order = orderService.createOrder(req);
        return ResponseEntity.ok(convertToDTO(order));
    }
}

// Слой Application (бизнес-логика)
@Service
public class OrderService {
    
    @Autowired
    private OrderRepository orderRepository; // @Repository
    
    @Autowired
    private PaymentService paymentService;   // @Service
    
    @Transactional
    public Order createOrder(OrderRequest request) {
        // Валидация
        if (request.getItems().isEmpty()) {
            throw new IllegalArgumentException("Order must have items");
        }
        
        // Создание заказа
        Order order = new Order();
        order.setItems(request.getItems());
        order.setTotal(calculateTotal(request.getItems()));
        
        // Сохранение в БД
        orderRepository.save(order);
        
        // Обработка платежа
        paymentService.charge(order.getTotal());
        
        return order;
    }
}

// Слой Infrastructure (доступ к данным)
@Repository
public class OrderRepository {
    
    @Autowired
    private EntityManager em;
    
    public void save(Order order) {
        em.persist(order);
    }
    
    public Order findById(Long id) {
        return em.find(Order.class, id);
    }
}

// Вспомогательный компонент
@Component
public class OrderCalculator {
    
    public BigDecimal calculateTax(BigDecimal total) {
        return total.multiply(new BigDecimal("0.13"));
    }
}

Таблица сравнения

┌──────────────┬──────────────┬──────────────┬──────────────┐
│ Аспект       │ @Component   │ @Service     │ @Repository  │
├──────────────┼──────────────┼──────────────┼──────────────┤
│ Назначение   │ Общее назн.  │ Бизнес-логика│ Доступ к ДБ  │
│ Область      │ Любая        │ Сервис слой  │ DAL слой     │
│ Особенности  │ Нет          │ Нет          │ Exception    │
│              │              │              │ translation  │
│ Обработка    │ Нет          │ Нет          │ Да           │
│ исключений   │              │              │ (SQL→Spring) │
│ @Transactnal │ Возможна     │ Рекомендуется│ Возможна      │
│ Паттерн      │ Utility      │ Service      │ DAO/Repo     │
└──────────────┴──────────────┴──────────────┴──────────────┘

Best Practice

// ✅ ПРАВИЛЬНО - ясная архитектура
@RestController              // Presentation
public class UserController { 
    @Autowired
    private UserService userService; // @Service - бизнес-логика
}

@Service                     // Application
public class UserService {
    @Autowired
    private UserRepository userRepository; // @Repository - DAL
}

interface UserRepository extends JpaRepository<User, Long> {
    // @Repository - Spring Data автоматически
}

// ❌ НЕПРАВИЛЬНО - смешивание ответственностей
@Component
public class UserManager { // Непонятно, что здесь? Бизнес? DAL?
    // Смешана бизнес-логика и доступ к ДБ
}

Вывод

  • @Component — базовая аннотация, используй когда ничего не подходит
  • @Service — для бизнес-логики, основной выбор для сервисов
  • @Repository — для доступа к данным, имеет специальную обработку исключений БД

Выбор правильной аннотации делает код более читаемым и позволяет Spring применить нужную обработку и аспекты.