PrepZone Logo
PrepZone

@Component, @Service, @Repository, @Controller

Stereotype annotations that tell Spring what role each class plays in your app.

Why this matters

  • Consistent stereotype usage makes the BookStore codebase navigable — any developer knows where to find controllers vs services.
  • @Repository enables automatic translation of persistence exceptions to Spring's DataAccessException hierarchy.
  • Mixing stereotypes incorrectly (business logic in a @Controller) breaks layering and testability.
ApplicationContext
BookController@RestController
BookService@Service
BookRepository@Repository
DataSourceAuto-configured

Arrows show @Autowired wiring — container injects at startup

The ApplicationContext reads configuration, creates beans, and wires dependencies automatically.

The stereotype hierarchy

All stereotypes are meta-annotated with @Component:

Java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Component
public @interface Service { }

Spring treats @Service, @Repository, @Controller, and @RestController identically for bean registration. The difference is semantic and enables specialised processing.

Stereotypes in BookStore

  • @Component — Generic bean; use for utilities, adapters, and infrastructure classes.
  • @Service — Business logic layer; BookService, OrderService, PricingService.
  • @Repository — Data access layer; BookRepository implementations and Spring Data interfaces.
  • @Controller — MVC controller returning view names (Thymeleaf pages).
  • @RestController — API controller returning serialized bodies (@Controller + @ResponseBody).

@Service in BookStore

Java
@Service
@Transactional(readOnly = true)
public class BookService {
    private final BookRepository repository;

    public BookService(BookRepository repository) {
        this.repository = repository;
    }

    public List<Book> findByGenre(String genre) {
        return repository.findByGenre(genre);
    }

    @Transactional
    public Book create(CreateBookRequest request) {
        Book book = new Book(request.title(), request.isbn(), request.price());
        return repository.save(book);
    }
}

@Service signals "business logic lives here" — no web or persistence concerns.

@Repository and Spring Data

Spring Data JPA repositories are interfaces annotated with @Repository:

Java
@Repository
public interface BookRepository extends JpaRepository<Book, Long> {
    List<Book> findByGenre(String genre);
    Optional<Book> findByIsbn(String isbn);
}

Spring generates the implementation at runtime. The @Repository stereotype also enables PersistenceExceptionTranslationPostProcessor — JDBC exceptions become DataAccessException subclasses.

@RestController for APIs

Java
@RestController
@RequestMapping("/api/books")
public class BookController {
    private final BookService bookService;

    public BookController(BookService bookService) {
        this.bookService = bookService;
    }

    @GetMapping
    public List<BookResponse> list() {
        return bookService.findAll().stream()
            .map(BookResponse::from)
            .toList();
    }
}

Controllers stay thin — delegate to services, map to DTOs, return HTTP responses.

@Component for everything else

Java
@Component
public class IsbnValidator {
    public boolean isValid(String isbn) {
        return isbn != null && isbn.replace("-", "").matches("\\d{13}");
    }
}

Use @Component when no more specific stereotype fits. Examples: validators, event listeners, scheduled task runners.

Component scanning boundaries

Stereotypes are discovered only under the scan root:

Java
@SpringBootApplication  // scans com.example.bookstore and below
public class BookStoreApplication { ... }

Add explicit scan paths when integrating a library:

Java
@SpringBootApplication(scanBasePackages = {
    "com.example.bookstore",
    "com.example.shared.security"
})

Naming and multiple implementations

Java
@Repository("jdbcBookRepository")
public class JdbcBookRepository implements BookRepository { ... }

@Repository("jpaBookRepository")
public class JpaBookRepository implements BookRepository { ... }

Bean names matter when using @Qualifier or @Resource(name = "...").

Stereotype vs @Bean

ApproachWhen to use
@Service on classYour own application classes
@Bean in @ConfigurationThird-party classes, factory methods, conditional creation
  • @Service on class

    When to useYour own application classes
  • @Bean in @Configuration

    When to useThird-party classes, factory methods, conditional creation
Java
@Configuration
public class HttpClientConfig {
    @Bean
    public RestClient pricingRestClient(BookStoreProperties props) {
        return RestClient.builder()
            .baseUrl(props.pricingServiceUrl())
            .build();
    }
}

You cannot add @Service to a library class — @Bean is the alternative.

Quick recall

Everything you need if you only revisit this box.

  • All stereotypes (@Service, @Repository, @Controller) are @Component specialisations.
  • @Service for business logic, @Repository for data access, @RestController for JSON APIs.
  • @Repository enables persistence exception translation to DataAccessException.
  • Use @Component for utilities and infrastructure without a clearer stereotype.
  • Component scanning finds stereotypes under the @SpringBootApplication package tree.
  • Use @Bean in @Configuration for third-party objects you cannot annotate directly.

Test yourself

Answer these before moving on — recall is what makes it stick.