1.4 Comprehensive Guide to Key Spring Annotations
The Spring framework handles a significant portion of its configuration through annotations. We've summarized the key annotations by category, along with practical Java code examples.
🏗️ 1. Stereotypes (Bean Registration)
When the Spring container (ApplicationContext) starts, it uses Component Scan to load classes marked with these annotations into memory as objects (Beans).
@Component: The most basic Spring-managed bean. Applied to general utility classes.@Service: Used for classes handling business logic (transaction management, domain logic execution).@Repository: Used for the Database Access layer (DAO). It has a special feature that catches lower-level DB framework exceptions and translates them into Spring's nativeDataAccessException.@Controller: Used for controllers that return traditional MVC HTML Views (JSP, Thymeleaf).@RestController: Used for REST API controllers that return pure data like JSON or XML instead of HTML. (It is the combination of@Controller+@ResponseBody)
// [Practical Stereotype Examples]
@Repository // 1. DB Access Layer
public class MemberRepository {
public void save(Member member) { /* Insert into DB */ }
}
@Service // 2. Business Logic Layer
@RequiredArgsConstructor
public class MemberService {
private final MemberRepository repository;
@Transactional
public void register(Member member) { repository.save(member); }
}
@RestController // 3. External API Controller Layer
@RequestMapping("/api/members")
@RequiredArgsConstructor
public class MemberController {
private final MemberService memberService;
@PostMapping
public String join(@RequestBody Member member) {
memberService.register(member);
return "SUCCESS"; // JSON (string) body is returned as is
}
}
💉 2. Dependency Injection (DI) & Manual Configuration
@Autowired: Instructs the Spring container to automatically inject registered beans based on Type. (Currently, constructor injection is highly recommended, making this annotation frequently omitted).@Qualifier("beanName"): When two or more beans implement the same interface, this annotation specifically targets the exact bean name to resolve conflicts.@Configuration&@Bean: Used as a pair when developers need to manually register external libraries (like Gson, RestTemplate) as a Bean into the Spring container, since you cannot attach@Componentto read-only library source code.
// [Manual Bean Registration Example]
@Configuration // "Spring, this class is a Bean Factory blueprint!"
public class AppConfig {
// Loads the external RestTemplate library into Spring Memory as a Singleton Bean
@Bean
public RestTemplate myRestTemplate() {
return new RestTemplate();
}
}
// [@Qualifier Conflict Resolution Example]
@Service
public class OrderService {
private final DiscountPolicy discountPolicy;
// If both 'RatePolicy' and 'FixPolicy' are registered Beans, this clearly specifies the target
public OrderService(@Qualifier("rateDiscountPolicy") DiscountPolicy discountPolicy) {
this.discountPolicy = discountPolicy;
}
}
🌐 3. Spring MVC (Web HTTP Communication)
These routing annotations decode and map incoming HTTP request packets from the client's browser into Java method executions.
@GetMapping,@PostMapping,@PutMapping,@DeleteMapping: Maps specific HTTP methods and URL paths to Java methods.@PathVariable: Extracts variable values declared dynamically within the URL path chunks. (/users/123-> 123)@RequestParam: Extracts Query String or HTML Form data attached after the URL question mark (?). (/list?page=2-> 2)@RequestBody: Directly deserializes the JSON chunk from the Client's HTTP Body into a Java Object (DTO).
// [Comprehensive Spring MVC Annotation APIs]
@RestController
@RequestMapping("/api/products") // Groups common URL prefixes together
public class ProductController {
// GET /api/products/99 -> Assigns 99 to the 'id' variable
@GetMapping("/{id}")
public ProductDto getProduct(@PathVariable("id") Long id) {
return productService.findById(id);
}
// GET /api/products/search?keyword=Macbook&limit=10
@GetMapping("/search")
public List<ProductDto> search(
@RequestParam("keyword") String keyword,
@RequestParam(value = "limit", defaultValue = "20") int limit) {
return productService.search(keyword, limit);
}
// POST /api/products + JSON Body {"name": "iPhone", "price": 100}
// The JSON string is injected directly into the fields of ProductCreateRequest!
@PostMapping
@ResponseStatus(HttpStatus.CREATED) // Specifies 201 Created instead of 200 OK on success
public void createProduct(@RequestBody ProductCreateRequest request) {
productService.create(request);
}
}
♻️ 4. Lifecycle & Infrastructure Properties
@PostConstruct: An initialization method executed exactly once, immediately after the Bean object is instantiated and@Autowireddependency injection is fully finished.@PreDestroy: A cleanup method invoked right before the Tomcat server shuts down, utilized to safely close open communication sockets or gracefully release resources.@Value: Exploited to aggressively read crucial configuration values or passwords written in theapplication.ymldirectly into a Java variable.
// [Lifecycle and Property Injection Example]
@Component
public class AwsS3Uploader {
// Identifies the cloud.aws.s3.bucket value in application.yml and injects it into 'bucket'
@Value("${cloud.aws.s3.bucket}")
private String bucket;
@PostConstruct // Automatically executes the moment Spring finishes assembling this class!
public void initAwsConnection() {
System.out.println("Opening connection to bucket: " + bucket + ". Ready!");
}
@PreDestroy // Executes the very absolute moment the Tomcat Shutdown button is pressed!
public void closeAwsConnection() {
System.out.println("Safely closing the S3 Socket connection.");
}
}
🛡️ 5. Validation & Other Critical Annotations
@Transactional: The magical annotation that opens a database transaction when entering a method block, automaticallyCommitting upon normal execution, andRollbacking perfectly if any RuntimeException erupts in transit.@Valid/@Validated: Acts as a frontline sentinel guarding HTTP endpoints by inspecting constraint annotations (checking for empty fields, correct text lengths) mapped inside incoming Java objects.@RestControllerAdvice: Formulates a global planetary exception center that aggregates and intercepts all exploding errors across the entire project's controllers into a single unified location.
// [Validation Example]
// DTO Class Definition
public class UserCreateRequest {
@NotBlank(message = "Name is absolutely mandatory!") // Strictly prohibits empty whitespaces
private String name;
@Min(value = 19, message = "Minors are restricted.") // Enforces minimum value of 19
private int age;
}
@RestController
public class UserController {
@PostMapping("/users")
// If the incoming JSON violates constraints established by @Valid (e.g., age dropping below 19),
// the method is utterly denied entry, instantly bouncing a 400 Bad Request exception to the Frontend.
public String createUser(@Valid @RequestBody UserCreateRequest request) {
userService.save(request);
return "Registration Successful";
}
}
🎯 Key Points
- Annotations drastically eliminate boilerplate code and remarkably escalate configuration productivity.
- Behind this overwhelming modern magic, one must fundamentally remember that the invisible underlying root technologies of the Spring Container, Reflection, and AOP Proxies are relentlessly orchestrating the behaviors in the background.