Spring Boot in Motion Spring Boot Intermediate

Beans, injection, and where @Transactional belongs

The ApplicationContext is a dependency graph

Spring's ApplicationContext is not a magic container — it is an explicit directed graph of objects (beans). When the app starts, Spring scans for @Component, @Service, @Repository, @Configuration, and @Bean factory methods, builds the graph, and resolves constructor parameters by type.

Prefer constructor injection

@Service
class OrderService {
    private final OrderRepository repo;
    private final PaymentProcessor payments;

    OrderService(OrderRepository repo, PaymentProcessor payments) {
        this.repo = repo;
        this.payments = payments;
    }

    @Transactional
    public Order place(OrderRequest req) { /* ... */ }
}

Constructor injection makes dependencies obvious in the signature, supports final fields, and enables trivially testable instantiation in unit tests without Spring.

Scopes: who owns the instance?

  • Singleton (default): one bean for the whole application.
  • Prototype: a new instance per injection — rarely needed; watch for subtle lifecycle bugs.
  • Request / Session: tie lifetime to a web conversation.

@Transactional lives at the service boundary

Transactions should wrap a business operation, not an individual SQL statement. Put @Transactional on the service method that commits-or-rolls-back as a unit. Repositories should stay dumb (SQL in, rows out); controllers should not know about transactions at all.

Open interactive lab →

Takeaways

  • Beans form a graph; the container resolves it by type at startup.
  • Constructor-inject, keep fields final, and test without Spring where you can.
  • Transactions go on service methods — one business operation, one transaction.

Enjoying This Lesson?

Your support helps create more comprehensive courses and lessons like this one. Help me build better learning experiences for everyone.

Support Awashyak