Lecture 28: Autowiring & Annotations in Spring

BMC201 - Web Technology

Mr. Prashant Kumar Nag

2026-03-12

Lecture 28

Autowiring & Annotations in Spring

Week 7 | Unit IV: Spring Framework Basics
BMC201 - Web Technology
Mr. Prashant Kumar Nag, Assistant Professor

Learning Objectives


  • Apply autowiring patterns
  • Use stereotype annotations
  • Disambiguate with @Qualifier and @Primary

Prerequisites


  • Core Java OOP concepts and interface-based design
  • Basic understanding of Servlets/JSP request flow from Unit III
  • Revision of Lecture 27 before moving into Autowiring & Annotations in Spring

Syllabus Mapping


  • Unit IV topic focus: Autowiring & Annotations in Spring
  • CO alignment: implementation understanding + architecture reasoning
  • Assessment alignment: short definitions + long implementation/design questions

Agenda


  • 5-minute recap from previous lecture
  • Concept deep dive: Autowiring & Annotations in Spring
  • Code/configuration walkthrough and output analysis
  • Debug checklist and exam-oriented summary

Introduction


Annotations reduce wiring boilerplate while preserving clarity.

Think About It


How does Spring choose one bean among many?

What Is Autowiring?


Autowiring is Spring’s automatic dependency resolution mechanism.

Instead of explicitly wiring beans in XML or Java configuration, Spring:

  • Scans for beans in the container
  • Matches dependencies by type, name, or qualifier
  • Injects the resolved bean automatically

This eliminates most manual bean wiring and reduces boilerplate configuration.

Why Use Autowiring?


Autowiring provides several advantages:

  • Less configuration: No need to declare every dependency explicitly
  • Type safety: Compile-time checking of dependency types
  • Faster development: Focus on business logic, not wiring mechanics
  • Cleaner code: Dependencies are clear from field/constructor declarations

Modern Spring applications rely heavily on annotation-driven autowiring.

Stereotype Annotations


Spring provides stereotype annotations to mark classes as beans:

Annotation Purpose Layer
@Component Generic Spring-managed bean Any
@Service Business logic layer Service
@Repository Data access layer DAO
@Controller Web presentation layer MVC Controller

All are specializations of @Component with semantic meaning.

@Component Annotation


@Component
public class EmailValidator {
    public boolean isValid(String email) {
        return email != null && email.contains("@");
    }
}

@Component
public class RegistrationService {
    @Autowired
    private EmailValidator validator;
    
    public void register(String email) {
        if (validator.isValid(email)) {
            // process registration
        }
    }
}

Spring automatically creates both beans and injects EmailValidator into RegistrationService.

@Service Annotation


@Service marks business logic components.

@Service
public class OrderService {
    @Autowired private OrderRepository repository;
    @Autowired private PaymentGateway paymentGateway;
    
    public void processOrder(Order order) {
        // business logic
        repository.save(order);
        paymentGateway.charge(order.getTotal());
    }
}

Semantically clearer than @Component and enables service-layer AOP.

@Repository Annotation


@Repository marks data access components.

@Repository
public class UserRepository {
    @Autowired private JdbcTemplate jdbcTemplate;
    
    public User findById(Long id) {
        return jdbcTemplate.queryForObject(
            "SELECT * FROM users WHERE id = ?",
            new UserRowMapper(), id
        );
    }
}

Enables automatic exception translation from persistence-specific exceptions to Spring’s DataAccessException.

@Controller Annotation


@Controller marks web layer components.

@Controller
public class HomeController {
    @Autowired private ProductService productService;
    
    @RequestMapping("/products")
    public String listProducts(Model model) {
        model.addAttribute("products", 
            productService.getAllProducts());
        return "productList";
    }
}

Used with Spring MVC for handling HTTP requests.

@Autowired Annotation


@Autowired tells Spring to inject a dependency automatically.

Can be used on:

  • Fields (most common, but less testable)
  • Constructors (recommended, enables immutability)
  • Setters (optional dependencies)
@Service
public class NotificationService {
    @Autowired private EmailService emailService;
}

Spring finds a bean of type EmailService and injects it.

Constructor Injection (Recommended)


@Service
public class OrderProcessor {
    private final OrderRepository repository;
    private final PaymentService paymentService;
    
    @Autowired  // optional since Spring 4.3 for single constructor
    public OrderProcessor(OrderRepository repository,
                         PaymentService paymentService) {
        this.repository = repository;
        this.paymentService = paymentService;
    }
}

Benefits: Immutable dependencies, easier testing, clear required dependencies

Field Injection


@Service
public class ReportGenerator {
    @Autowired private DataService dataService;
    @Autowired private TemplateEngine templateEngine;
    
    public Report generate() {
        // use dependencies
    }
}

Pros: Concise, less boilerplate

Cons: Cannot make fields final, harder to unit test, hides dependencies

Setter Injection


@Service
public class CacheManager {
    private CacheProvider cacheProvider;
    
    @Autowired(required = false)
    public void setCacheProvider(CacheProvider cacheProvider) {
        this.cacheProvider = cacheProvider;
    }
}

Best for: Optional dependencies with required = false

Note: Dependencies can be changed after construction

Autowiring Resolution Strategy


When @Autowired is used, Spring resolves dependencies:

  1. By Type — Find beans matching the required type
  2. If multiple matches — Apply disambiguation:
    • Check for @Primary bean
    • Match by parameter/field name
    • Look for @Qualifier annotation
  3. If no match — Throw NoSuchBeanDefinitionException (unless required = false)

Type-based autowiring is the default and most common approach.

The Ambiguity Problem


public interface Notifier {
    void send(String message);
}

@Component
public class EmailNotifier implements Notifier { }

@Component
public class SmsNotifier implements Notifier { }

@Service
public class AlertService {
    @Autowired Notifier notifier;  // Which one?
}

Error: NoUniqueBeanDefinitionException — Spring finds two Notifier beans

Solution 1: @Primary


@Component
public class EmailNotifier implements Notifier { }

@Component
@Primary  // This one wins when ambiguous
public class SmsNotifier implements Notifier { }

@Service
public class AlertService {
    @Autowired Notifier notifier;  // gets SmsNotifier
}

@Primary marks a bean as the default choice when multiple candidates exist.

Use when one implementation is clearly the default.

Solution 2: @Qualifier


@Component("emailNotifier")
public class EmailNotifier implements Notifier { }

@Component("smsNotifier")
public class SmsNotifier implements Notifier { }

@Service
public class AlertService {
    @Autowired 
    @Qualifier("emailNotifier")
    private Notifier notifier;  // explicitly choose email
}

@Qualifier specifies which bean to inject by name.

Use when you need explicit control over which implementation to use.

Custom Qualifier Annotations


@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Email { }

@Component @Email
public class EmailNotifier implements Notifier { }

@Service
public class AlertService {
    @Autowired @Email
    private Notifier notifier;  // type-safe qualifier
}

Custom qualifiers provide type-safe, refactor-friendly disambiguation.

Autowiring Collections


@Service
public class NotificationHub {
    @Autowired
    private List<Notifier> allNotifiers;
    
    public void broadcast(String message) {
        for (Notifier n : allNotifiers) {
            n.send(message);
        }
    }
}

Spring automatically injects all beans of type Notifier into the list.

Works with List, Set, Map<String, T> (key = bean name).

Optional Dependencies


@Service
public class ReportService {
    @Autowired(required = false)
    private TemplateCustomizer customizer;
    
    public Report generate() {
        if (customizer != null) {
            customizer.customize(report);
        }
        return report;
    }
}

Use required = false when dependency is optional and may not exist.

Alternative: Use Optional<T> or ObjectProvider<T>

Autowiring Best Practices


  1. Prefer constructor injection for required dependencies
  2. Use field injection sparingly (quick prototypes only)
  3. Mark defaults with @Primary when one implementation dominates
  4. Use @Qualifier for explicit control or multiple implementations
  5. Avoid circular dependencies (constructor injection makes them obvious)
  6. Use @Autowired(required = false) or Optional<T> for optional deps

Constructor injection + @Primary/@Qualifier covers 95% of real use cases.

Enabling Component Scanning


@Configuration
@ComponentScan(basePackages = "com.example.myapp")
public class AppConfig {
}

@ComponentScan tells Spring where to look for @Component, @Service, etc.

Spring Boot enables this automatically for the package and sub-packages of the main application class.

Autowiring and Annotations


flowchart LR
  A["@Component Scan"] --> B["Bean Registry"]
  B --> C["@Autowired Injection Point"]
  C --> D{"Multiple Candidates?"}
  D -->|No| E["Inject Bean"]
  D -->|Yes| F["Resolve by @Qualifier / @Primary"]
  F --> E

  • Stereotype annotations register beans automatically
  • @Autowired resolves dependencies by type
  • @Qualifier and @Primary solve ambiguity

Code Walkthrough


@Service
class AlertService {
  @Autowired @Qualifier("emailNotifier")
  Notifier notifier;
}

@Component("emailNotifier")
class EmailNotifier implements Notifier {}

@Component("smsNotifier")
@Primary
class SmsNotifier implements Notifier {}

Memory Booster


Syllabus memory points for Autowiring & Annotations in Spring:

  • Core recall: @Autowired, @Component, @Service, @Repository
  • Exam compare: Manual wiring vs annotation-driven autowiring
  • Practical anchor: Build service graph with annotation-based injection

Live Demo


Live implementation for Autowiring & Annotations in Spring:

?? Open Demo: Lecture 28 - Autowiring & Annotations in Spring

Demo checklist: - Register two Notifier beans and trigger autowiring ambiguity - Resolve ambiguity first using @Primary, then with @Qualifier - Demonstrate constructor injection as best-practice alternative - Break one annotation intentionally and trace startup error

Resources & References


Structured Debug Checklist


  1. verify the primary API usage for Autowiring & Annotations in Spring is correct (imports, method names, config)
  2. check request/bean/session flow and object lifecycle assumptions
  3. inspect server logs for the first exception (not just the final symptom)
  4. reproduce one failing case and one passing case before finalizing fixes

Exam Preparation Questions: Short


  • Define Autowiring & Annotations in Spring with one practical use case.
  • Write/identify the key API or construct: @Autowired, @Component, @Service, @Repository.
  • Differentiate: Manual wiring vs annotation-driven autowiring.
  • Mention one common implementation error and correction.

Exam Preparation Questions: Long


  • Explain Autowiring & Annotations in Spring with architecture/flow and implementation steps.
  • Write a structured answer comparing two approaches used in this topic.
  • Discuss debugging strategy for this topic with likely failure points.

Practice Task


  • Implement: Build service graph with annotation-based injection.
  • Add console/log output to validate flow step-by-step.
  • Document one bug you encountered and the exact fix.

Checklist


Can you:

  • explain Autowiring & Annotations in Spring in your own words?
  • implement a basic example end-to-end?
  • identify and fix one common runtime issue?

Next Lecture


  • Topic: Lecture 29 - Introduction to Design Patterns in Spring
  • Preparation required: revise this lecture summary and code walkthrough

Questions?

Next: Lecture 29