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

Что делает @Service?

1.2 Junior🔥 191 комментариев
#Spring Framework

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

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

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

Аннотация @Service в Spring Framework

@Service — это одна из основных стереотипных аннотаций в Spring, которая служит для обозначения класса как сервисного слоя (service layer) приложения. Это не просто декоративная аннотация, она выполняет конкретные и важные функции в контексте архитектуры приложения.

Основное назначение @Service

@Service говорит Spring контейнеру: «Это класс бизнес-логики, создай его бин, управляй его жизненным циклом и позволь внедрять его в другие компоненты». Аннотация помечает класс как компонент приложения, который обрабатывает бизнес-логику и координирует операции между слоем доступа к данным (репозиторий) и слоем представления (контроллер).

Что конкретно делает @Service

1. Регистрация в контексте Spring

@Service
public class UserService {
    // Класс автоматически становится бином в контексте Spring
}

Когда Spring сканирует classpath (обычно с помощью @ComponentScan или @SpringBootApplication), он находит все классы с @Service и создаёт их экземпляры как управляемые бины.

2. Инъекция зависимостей (Dependency Injection)

@Service
public class UserService {
    
    private final UserRepository userRepository;
    private final EmailService emailService;
    
    // Конструктор для DI
    public UserService(UserRepository userRepository, EmailService emailService) {
        this.userRepository = userRepository;
        this.emailService = emailService;
    }
    
    public void registerUser(String email, String password) {
        // Бизнес-логика
        User user = new User(email, password);
        userRepository.save(user);
        emailService.sendWelcomeEmail(email);
    }
}

Другие компоненты (контроллеры, другие сервисы) могут внедрять UserService через конструктор, setter или field injection.

Архитектурный слой: где находится @Service

@Service — это слой бизнес-логики в типичной трёхслойной архитектуре:

┌─────────────────────────────────────┐
│   Presentation Layer (@RestController)
│   - HTTP запросы/ответы             │
│   - Валидация входных данных        │
└────────────┬────────────────────────┘
             │ зависит от
┌────────────▼────────────────────────┐
│   Business Logic Layer (@Service)    │
│   - Основная бизнес-логика          │
│   - Координация операций             │
│   - Транзакции (@Transactional)      │
└────────────┬────────────────────────┘
             │ зависит от
┌────────────▼────────────────────────┐
│   Data Access Layer (@Repository)    │
│   - CRUD операции с БД               │
│   - SQL запросы                      │
└─────────────────────────────────────┘

Наследование от @Component

@Service — это специализированная версия @Component. В исходном коде Spring это выглядит так:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Service {
    @AliasFor(annotation = Component.class)
    String value() default "";
}

Всё, что делает @Service — это украшает класс с помощью @Component и предоставляет семантическое значение: этот класс — часть сервисного слоя.

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

// 1. Сущность (Domain Model)
public class Product {
    private Long id;
    private String name;
    private Double price;
    // getters, setters...
}

// 2. Репозиторий (Data Access Layer)
@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {
    List<Product> findByPriceGreaterThan(Double price);
}

// 3. Сервис (Business Logic Layer)
@Service
public class ProductService {
    
    private final ProductRepository productRepository;
    private final NotificationService notificationService;
    
    public ProductService(ProductRepository productRepository, 
                          NotificationService notificationService) {
        this.productRepository = productRepository;
        this.notificationService = notificationService;
    }
    
    @Transactional
    public void addProduct(String name, Double price) {
        // Валидация
        if (price <= 0) {
            throw new IllegalArgumentException("Цена должна быть положительной");
        }
        
        // Создание и сохранение
        Product product = new Product();
        product.setName(name);
        product.setPrice(price);
        productRepository.save(product);
        
        // Сопутствующие операции
        notificationService.notifyAdmins("Новый товар: " + name);
    }
    
    public List<Product> getExpensiveProducts(Double minPrice) {
        return productRepository.findByPriceGreaterThan(minPrice);
    }
}

// 4. Контроллер (Presentation Layer)
@RestController
@RequestMapping("/api/products")
public class ProductController {
    
    private final ProductService productService;
    
    public ProductController(ProductService productService) {
        this.productService = productService;
    }
    
    @PostMapping
    public ResponseEntity<String> createProduct(@RequestParam String name, 
                                                @RequestParam Double price) {
        productService.addProduct(name, price);
        return ResponseEntity.ok("Товар создан");
    }
    
    @GetMapping("/expensive")
    public List<Product> getExpensive(@RequestParam Double minPrice) {
        return productService.getExpensiveProducts(minPrice);
    }
}

Другие стереотипные аннотации

Spring предоставляет несколько похожих аннотаций для разных слоёв:

  • @Component — общая аннотация для любого управляемого бина
  • @Service — для бизнес-логики (как в нашем примере)
  • @Repository — для доступа к данным, также обеспечивает трансляцию исключений БД
  • @Controller — для обработки веб-запросов (MVC)
  • @RestController — комбинация @Controller + @ResponseBody для REST API

Ключевые преимущества использования @Service

  • Ясность намерения — быстро понятно, что это класс бизнес-логики
  • Разделение ответственности — каждый слой имеет свою роль
  • Управление транзакциями — часто используется @Transactional в сервисах
  • Повторное использование кода — сервис можно внедрить в любой другой компонент
  • Тестирование — легко создавать моки зависимостей при unit-тестировании
  • Область видимости — по умолчанию создаётся как Singleton (один экземпляр на приложение)
Что делает @Service? | PrepBro