[Spring Boot] Annotations

brandon·2025년 6월 5일

spring-boot

목록 보기
10/15

@Configuration

Indicates a Configuration Class:
The primary purpose of @Configuration is to signal to the Spring IoC (Inversion of Control) container that a class contains @Bean definition methods. This means that within this class, you'll be defining and configuring objects (beans) that Spring should manage.

Source of Bean Definitions:
Classes annotated with @Configuration are essentially a replacement for traditional XML-based Spring configuration files. Instead of writing tags in an XML file, you create methods annotated with @Bean within your @Configuration class. These methods return instances of the objects you want Spring to manage.

Example:


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {

    @Bean
    public MyService myService() {
        return new MyServiceImpl();
    }

    @Bean
    public MyRepository myRepository() {
        return new MyRepositoryImpl();
    }
}

In this example, myService() and myRepository() are methods that define Spring beans. When the Spring application context starts, it will call these methods and register the returned objects as managed beans.

Ensures Singleton Behavior (by default):
One of the key benefits of @Configuration classes is that they guarantee singleton behavior for beans defined within them, even if you call @Bean methods multiple times within the same configuration class to define dependencies. Spring achieves this by creating a CGLIB-enhanced subclass at runtime. This subclass intercepts calls to @Bean methods and checks if a bean with that name already exists in the container. If it does, it returns the existing instance; otherwise, it creates a new one. This ensures that only one instance of a singleton bean is created.

You can control this behavior with proxyBeanMethods = false in @Configuration(proxyBeanMethods = false), which can be useful for performance in certain scenarios, but it means cross-method calls between @Bean methods will result in new instances being created.

Enables Inter-bean Dependencies:
Within a @Configuration class, you can easily define dependencies between your beans by calling other @Bean methods. Spring intelligently handles these calls, ensuring that the correct (often singleton) instances are injected.

Example:


@Configuration
public class AppConfig {

    @Bean
    public MyRepository myRepository() {
        return new MyRepositoryImpl();
    }

    @Bean
    public MyService myService() {
        // myRepository() is called, but Spring ensures the singleton instance is used
        return new MyServiceImpl(myRepository());
    }
}

Works in Conjunction with @SpringBootApplication:
In Spring Boot applications, the @SpringBootApplication annotation (which you typically put on your main application class) implicitly includes @Configuration. This means that if your main application class or any classes it scans are annotated with @Configuration, Spring Boot will automatically pick them up and process them for bean definitions.

In essence, @Configuration is the foundation for modern, Java-based Spring (and Spring Boot) applications, allowing you to define and manage your application's components programmatically in a clear and organized manner.

@Profile

What are Spring Boot Profiles?

  • Environment-Specific Configuration: Applications often require different settings depending on where they are deployed. For example:
    • Development: You might use an in-memory database (like H2), relaxed security, and extensive logging.
    • Production: You'd use a robust relational database (like MySQL or PostgreSQL), strict security, and optimized logging.
    • Selective Bean Loading: Profiles allow you to conditionally load Spring Beans (components, services, configurations) based on the active profile(s). This means you can have different implementations of a service for different environments without changing the core application code.
    • Configuration Files: Spring Boot supports profile-specific configuration files. For instance, application-dev.properties (or .yml) would contain properties specific to the "dev" profile, while application-prod.properties would have production-specific settings. The base application.properties (or .yml) holds common configurations that apply across all profiles.
  • Profile Groups: You can group multiple profiles together. For example, a "production" group might include "proddb" and "prodmq" profiles, activating all of them with a single command.

Why are Profiles Crucial?

  • Flexibility and Maintainability: They prevent hardcoding environment-specific values directly into your codebase. This makes your application more flexible and easier to maintain as it moves through different stages of development and deployment.

  • Reduced Errors: By isolating configurations, you minimize the risk of accidentally deploying development settings to a production environment.

  • Simplified Deployment: Instead of maintaining separate codebases or manually changing configurations for each environment, you simply activate the appropriate profile.

  • Clean Code: Profiles promote cleaner code by separating concerns related to environment-specific logic and configuration.

How to Use Spring Boot Profiles:

  1. Define Profile-Specific Configuration Files:
    Create files like:
  • application.properties (or application.yml): For common properties.
  • application-dev.properties: For development environment settings.
  • application-prod.properties: For production environment settings.
    And so on, for other environments (e.g., application-test.properties, application-qa.properties).
  1. Annotate Components and Configurations with @Profile:
    You can use the @Profile annotation on classes annotated with @Component, @Configuration, or @ConfigurationProperties to specify that they should only be loaded when a particular profile is active.

@Configuration
@Profile("dev")
public class DevelopmentDataSourceConfig {
    // ... configure H2 database
}

@Configuration
@Profile("prod")
public class ProductionDataSourceConfig {
    // ... configure MySQL database
}
  1. Activate Profiles:
    You can activate profiles in several ways, with different priorities:
  • application.properties / application.yml:
spring.profiles.active=dev
  • Command Line Argument:
java -jar your-app.jar --spring.profiles.active=prod
  • JVM System Property:
java -Dspring.profiles.active=test -jar your-app.jar
  • Environment Variable:
export SPRING_PROFILES_ACTIVE=qa
java -jar your-app.jar
  • Programmatically: Before the application runs, using SpringApplication.setAdditionalProfiles().
  • JUnit Tests: Using the @ActiveProfiles annotation.

@ControllerAdvice

What is @ControllerAdvice?

  • It's a specialized @Component annotation, meaning classes annotated with @ControllerAdvice are automatically detected and registered as Spring beans through component scanning.
  • It acts as a global handler or advisor for your controllers.
  • It was introduced in Spring 3.2 to address the limitations of handling concerns like exceptions, model attributes, and data binding on a per-controller basis.

What is it used for?

The primary use cases for @ControllerAdvice are:

  • Global Exception Handling: This is the most common and powerful use of @ControllerAdvice. Instead of handling specific exceptions within each controller method (using @ExceptionHandler directly in the controller), you can define a class with @ControllerAdvice to handle exceptions thrown by any controller method across your entire application. This leads to cleaner, more maintainable code and consistent error responses.

You define methods within the @ControllerAdvice class annotated with @ExceptionHandler to specify which exception types they handle.
These methods can return custom error messages, specific HTTP status codes (using @ResponseStatus), or even complex error response objects (e.g., JSON for REST APIs).
Global Model Attributes (@ModelAttribute): You can use @ControllerAdvice to add common data to the model of all or a subset of your controllers. This is useful for information that needs to be available on every view, such as user details, application-wide settings, or navigation data.

Methods annotated with @ModelAttribute within a @ControllerAdvice class will be executed before any @RequestMapping method in your controllers, populating the model with the specified attributes.
Global Data Binding (@InitBinder): @ControllerAdvice allows you to configure WebDataBinder instances globally. This is useful for customizing how request parameters are bound to objects, for example, by registering custom property editors or validators.

Methods annotated with @InitBinder within a @ControllerAdvice class will be executed before data binding occurs for any controller.
How it Works:

When an HTTP request comes into a Spring MVC application:

Request Mapping: Spring identifies the appropriate controller method to handle the request based on @RequestMapping (or its specialized variants like @GetMapping, @PostMapping, etc.).
Controller Advice Interception: Before and after the controller method executes, Spring checks for any @ControllerAdvice beans.
Applying Advice:
@ModelAttribute and @InitBinder: Global @ModelAttribute and @InitBinder methods (from @ControllerAdvice) are applied before local ones (from the @Controller).
@ExceptionHandler: When an exception is thrown by a controller method, Spring looks for an appropriate @ExceptionHandler method:
It first looks for a local @ExceptionHandler within the throwing controller itself.
If no local handler is found, it then looks for a matching global @ExceptionHandler method defined in any @ControllerAdvice class.
If a match is found, that handler method is executed to produce an appropriate error response.
Global @ExceptionHandler methods are applied after local ones.
Targeting Specific Controllers:

By default, @ControllerAdvice methods apply to all controllers in your application. However, you can narrow down their scope using attributes on the @ControllerAdvice annotation:

annotations: Target controllers annotated with specific annotation types (e.g., @ControllerAdvice(annotations = RestController.class)).
assignableTypes: Target controllers that are assignable to specific classes (e.g., @ControllerAdvice(assignableTypes = {UserController.class, AdminController.class})).
basePackages (or value): Target controllers within specific packages (e.g., @ControllerAdvice("com.example.controllers")).
basePackageClasses: Type-safe alternative to basePackages, using marker classes within packages.
@RestControllerAdvice:

Spring also provides @RestControllerAdvice, which is a composed annotation equivalent to @ControllerAdvice plus @ResponseBody. This is particularly useful for REST APIs, as it automatically serializes the return value of @ExceptionHandler methods to the response body (e.g., JSON or XML), eliminating the need to explicitly add @ResponseBody to each handler method.

Benefits of @ControllerAdvice:

Centralized Concern Handling: Consolidates common logic (exception handling, model attributes, data binding) in one place.
Reduced Boilerplate: Avoids repeating the same code in multiple controllers.
Improved Code Organization: Makes your controllers cleaner and more focused on their primary responsibility.
Consistent Error Responses: Ensures a uniform error format across your application, improving user experience and API consistency.
Maintainability: Easier to manage and modify global behaviors.
In summary, @ControllerAdvice is a crucial annotation in Spring for building robust, maintainable, and well-structured web applications by enabling global, cross-cutting logic for your controllers.

profile
everything happens for a reason

0개의 댓글