Essential Spring Boot Annotations Guide
Essential Spring Boot Annotations Guide
Introduction
Spring Boot has emerged as a leading framework for the rapid development of
production-ready Java applications. Its philosophy of convention over configuration
significantly reduces the boilerplate code typically associated with enterprise Java
development, allowing developers to focus on the core business logic. A central aspect
of Spring Boot's approach to simplifying development is the extensive use of
annotations. These annotations serve as a form of metadata that provides instructions
to the Spring framework, enabling declarative programming and streamlining various
aspects of application configuration and management. This report aims to provide a
comprehensive guide to the essential annotations commonly employed in Spring Boot
applications, categorizing them based on their primary functionalities. Understanding
these annotations is crucial for developers seeking to leverage the full potential of the
Spring Boot framework and build efficient, maintainable, and robust applications. The
inclusion of practical examples will further clarify their usage.
---------------------------------------------------------------------------------------------------------------------
-----
2.1. @SpringBootApplication
The @Configuration aspect signifies that the class can declare one or more beans, which
are managed by the Spring container.1 This annotation marks the class as a source of
bean definitions, offering a Java-based alternative to traditional XML configuration.2
@EnableAutoConfiguration plays a critical role in automating the setup by instructing
Spring Boot to inspect the project's classpath and automatically configure the
application based on the dependencies added.1
@ComponentScan is responsible for directing Spring to the packages that should be
scanned to discover components (beans) that need to be managed by the Spring
container.1
By consolidating these three vital functionalities, @SpringBootApplication provides a
streamlined approach to bootstrapping a Spring Boot application with a single
annotation.2
🔹 Example:
🔹 Java
package [Link];
import [Link];
import [Link];
@SpringBootApplication // Combines @Configuration, @EnableAutoConfiguration,
@ComponentScan
public class MyApplication {
public static void main(String[] args) {
[Link]([Link], args);
}
}
// By default, scans components in [Link] and its sub-packages.
🔹 2.2. @Configuration
🔹 Example:
🔹 Java
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@Configuration // Marks this class as a source of bean definitions
public class AppConfig {
@Bean // Declares a bean named 'emailService'
public EmailService emailService() {
return new EmailService(); // Instantiate and configure the bean
}
@Bean("notificationService") // Declares a bean with a custom name
public SMSService smsService() {
return new SMSService();
}
}
2.3. @EnableAutoConfiguration
@EnableAutoConfiguration is instrumental in automating the configuration of a Spring
Boot application.1 This annotation instructs Spring Boot to examine the project's
classpath and automatically configure the Spring application context based on the
dependencies found.1 For instance, if spring-boot-starter-web is present, Spring Boot
automatically configures an embedded web server and Spring MVC. This intelligent
automation embodies Spring Boot's principle of convention over configuration.2
@EnableAutoConfiguration is implicitly included when using @SpringBootApplication.1
🔹 Java
package [Link];
import [Link];
import [Link];
import [Link];
🔹 @Configuration
🔹 Java
package [Link];
import [Link];
import [Link];
import [Link];
@SpringBootApplication // Includes default ComponentScan
@ComponentScan(basePackages = {"[Link]",
"[Link]", "[Link]"})
// Overrides default scan to include specific packages, including external ones
public class MyApplicationWithCustomScan {
public static void main(String[] args) {
[Link]([Link], args);
}
}
2.5. @SpringBootConfiguration
@SpringBootConfiguration is a class-level annotation indicating that a class provides
application configuration.2 It's essentially an alias for @Configuration but with specific
semantics allowing configuration to be automatically located, especially useful in testing
scenarios.7 Most applications use @SpringBootApplication, which includes this
implicitly.7
🔹 Java
package [Link];
import [Link];
import [Link];
@SpringBootConfiguration // Alias for @Configuration, helps with auto-detection in
tests
public class CustomAppConfiguration {
🔹 @Bean
🔹 3.1. @Bean
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
🔹 @Configuration
🔹 @Bean
🔹 @Bean
🔹 3.2. @Component
🔹 Example:
🔹 Java
package [Link];
import [Link];
@Component // Marks this class as a generic Spring component
public class DataFormatter {
public String format(Object data) {
// Formatting logic...
return [Link]();
}
}
🔹 3.3. @Service
🔹 Example:
🔹 Java
package [Link];
import [Link];
import [Link];
import [Link];
@Service // Marks this class as a service component
public class UserService {
private final UserRepository userRepository;
@Autowired // Constructor injection
public UserService(UserRepository userRepository) {
[Link] = userRepository;
}
public User findUserById(Long id) {
return [Link](id).orElse(null);
}
// Other business logic methods...
}
🔹 3.4. @Repository
package [Link];
import [Link];
import [Link];
import [Link]; // Optional with Spring Data JPA,
but good practice
@Repository // Marks this interface/class as a data access component and enables
exception translation
public interface UserRepository extends JpaRepository<User, Long> {
// Spring Data JPA automatically implements basic CRUD methods
// Can add custom query methods here
User findByUsername(String username);
}
🔹 Java
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@Repository // Marks this class as a data access component and enables exception
translation
public class ProductRepositoryImpl implements ProductRepository {
private final JdbcTemplate jdbcTemplate;
public ProductRepositoryImpl(DataSource dataSource) {
[Link] = new JdbcTemplate(dataSource);
}
🔹 @Override
🔹 3.5. @Autowired
The @Autowired annotation enables automatic dependency injection.1 Spring finds a
matching bean in the context and injects it into fields, constructors, or setter methods.1
Constructor injection is generally preferred.2
🔹 Java
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
🔹 @Controller
🔹 @Autowired
🔹 @Autowired
🔹 3.6. @Qualifier
The @Qualifier annotation is used with @Autowired to specify which bean to inject
when multiple candidates of the same type exist.2 It references the bean's unique
identifier (default name or custom name).15
🔹 Example:
🔹 Java
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
🔹 @Configuration
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
🔹 @Service
🔹 @Autowired
public OrderService(@Qualifier("emailSender") NotificationSender notificationSender)
{ // Specify "emailSender" bean
[Link] = notificationSender;
}
public void placeOrder() {
// ... logic
[Link]("Order placed successfully!");
}
}
🔹 3.7. @Primary
The @Primary annotation indicates the preferred bean when multiple candidates of the
same type exist for autowiring, unless explicitly specified otherwise with @Qualifier.9,
15
🔹 Example:
🔹 Java
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
🔹 @Configuration
🔹 @Service
🔹 @Autowired
🔹 3.8. @Lazy
The @Lazy annotation delays the initialization of a bean until it's first requested,
overriding the default eager initialization of singletons.8, 15 This can improve startup
time or help resolve circular dependencies.15
🔹 Example:
🔹 Java
package [Link];
import [Link];
import [Link];
import [Link];
🔹 @Service
@Lazy // This bean will only be created when first injected or requested
public class HeavyResourceService {
public HeavyResourceService() {
}
public void performAction() {
}
}
🔹 @Component
🔹 @Autowired
🔹 @Override
🔹 [Link]("ApplicationRunner: Starting...");
🔹 [Link]("ApplicationRunner: Finished.");
}
}
4. REST API Development Annotations
4.1. @RestController
@RestController is a convenience annotation combining @Controller and
@ResponseBody.1 It marks a class as a controller where handler methods return
domain objects directly converted to the response body (usually JSON/XML), suitable for
REST APIs.2
🔹 Example:
🔹 Java
package [Link];
import [Link];
import [Link];
import [Link];
import [Link].*;
import [Link];
@RestController // Combines @Controller and @ResponseBody for all methods
@RequestMapping("/api/products") // Base path for all methods in this controller
public class ProductRestController {
🔹 @Autowired
🔹 4.2. @Controller
The @Controller annotation marks a class as a Spring MVC controller for handling web
requests.2 Unlike @RestController, it's typically used in traditional web apps where
methods return view names (e.g., for Thymeleaf, JSP) rather than directly writing to the
response body.6
🔹 Example:
🔹 Java
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@Controller // Standard MVC Controller
@RequestMapping("/products")
public class ProductWebController {
🔹 @Autowired
🔹 Example:
🔹 Java
package [Link];
import [Link];
import [Link].*;
@RestController
}
// Maps POST requests to /api/items
@RequestMapping(method = [Link])
public ResponseEntity<String> createItem(@RequestBody String itemData) {
}
}
4.4. @GetMapping, @PostMapping, @PutMapping, @DeleteMapping, @PatchMapping
These are shortcuts for @RequestMapping specific to HTTP methods (GET, POST, PUT,
DELETE, PATCH).1 They improve readability.20
🔹 Example:
🔹 Java
package [Link];
import [Link];
import [Link];
import [Link].*;
@RestController
@RequestMapping("/api/users")
public class UserShortcutController {
@GetMapping("/{id}") // Shortcut for [Link]
public User getUser(@PathVariable Long id) {
// ... find user by id
return new User(id, "Example User"); // Placeholder
}
@PostMapping // Shortcut for [Link]
public ResponseEntity<User> createUser(@RequestBody User user) {
// ... save user
return [Link](201).body(user);
}
@PutMapping("/{id}") // Shortcut for [Link]
public User updateUser(@PathVariable Long id, @RequestBody User user) {
// ... update user by id
[Link](id); // Ensure ID matches path
return user;
}
@DeleteMapping("/{id}") // Shortcut for [Link]
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
// ... delete user by id
return [Link]().build();
}
@PatchMapping("/{id}") // Shortcut for [Link]
public User partiallyUpdateUser(@PathVariable Long id, @RequestBody
[Link]<String, Object> updates) {
// ... apply partial updates to user by id
return new User(id, "Partially Updated User"); // Placeholder
}
}
// Dummy User class for example
class User {
private Long id;
private String name;
public User(Long id, String name) { [Link] = id; [Link] = name; }
public Long getId() { return id; }
public void setId(Long id) { [Link] = id; }
public String getName() { return name; }
public void setName(String name) { [Link] = name; }
}
4.5. @PathVariable
The @PathVariable annotation extracts values from URI template variables
(placeholders like {id}) and binds them to method parameters.1, 2
🔹 Example:
🔹 Java
package [Link];
import [Link].*;
@RestController
@RequestMapping("/api/orders")
public class OrderController {
// Extracts 'orderId' from the path /api/orders/{orderId}
@GetMapping("/{orderId}")
public String getOrderDetails(@PathVariable Long orderId) {
🔹 return "Details for Order ID: " + orderId;
}
// Extracts 'customerId' and 'orderId' from
/api/customers/{customerId}/orders/{orderId}
@GetMapping("/customers/{customerId}/orders/{orderId}")
public String getCustomerOrder(
@PathVariable("customerId") String custId, // Can specify name if different from param
@PathVariable Long orderId) {
🔹 return "Details for Order ID: " + orderId + " for Customer: " + custId;
}
}
4.6. @RequestParam
The @RequestParam annotation extracts query parameters (e.g., ?name=value) from
the request URL and binds them to method parameters.2 It supports required/optional
status and default values.6
🔹 Example:
🔹 Java
package [Link];
import [Link].*;
import [Link];
import [Link];
@RestController
@RequestMapping("/api/search")
public class SearchController {
// Handles requests like /api/search/products?query=laptop
@GetMapping("/products")
public String searchProducts(
@RequestParam String query, // Required parameter
@RequestParam(required = false) String category, // Optional parameter
@RequestParam(defaultValue = "10") int size, // Parameter with default value
@RequestParam(name = "sort") Optional<String> sortOrder // Optional using Java 8
Optional
){
StringBuilder response = new StringBuilder();
[Link]("Searching for '").append(query).append("'");
if (category != null) {
[Link](" in category '").append(category).append("'");
}
return [Link]();
}
// Handles requests like /api/search/users?role=ADMIN&role=SUPPORT
@GetMapping("/users")
public String searchUsersByRole(@RequestParam List<String> role) {
🔹 return "Searching for users with roles: " + [Link](", ", role);
}
}
4.7. @RequestBody
The @RequestBody annotation binds the HTTP request body content (e.g., JSON, XML)
to a method parameter.1 Spring uses HttpMessageConverters for the conversion.2
Commonly used with POST, PUT, PATCH.
🔹 Example:
🔹 Java
package [Link];
import [Link]; // Assume Product is a POJO
import [Link];
import [Link].*;
@RestController
@RequestMapping("/api/products")
public class ProductApiController {
// Binds the JSON/XML body of the POST request to the product parameter
@PostMapping
public ResponseEntity<Product> createProduct(@RequestBody Product product) {
🔹 Java
package [Link];
import [Link]; // Assume a simple POJO
import [Link];
import [Link];
import [Link]; // Explicitly needed
here
@Controller // Not a @RestController
@RequestMapping("/app-status")
public class StatusController {
@GetMapping("/health")
@ResponseBody // Ensures the return value is written to the response body as
JSON/XML
public StatusResponse getHealthStatus() {
return new StatusResponse("OK", "Application is running");
}
@GetMapping("/info")
public String getInfoPage() {
// Without @ResponseBody, this returns a view name
return "application-info";
}
}
5. Spring Data JPA Annotations
🔹 5.1. @Entity
The @Entity annotation (from [Link]) marks a Java class as a JPA entity,
representing a row in a database table.24 Requires a primary key (@Id).27
🔹 Example:
🔹 Java
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@Entity // Marks this class as a JPA entity
public class Customer {
@Id // Marks this field as the primary key
@GeneratedValue(strategy = [Link]) // Configures auto-generation
private Long id;
private String firstName;
private String lastName;
}
🔹 5.2. @Table
The @Table annotation specifies details of the database table mapped to the entity, like
table name, schema, and unique constraints.24
🔹 Example:
🔹 Java
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
🔹 @Entity
🔹 @Id
🔹 5.3. @Id
The @Id annotation marks a field as the primary key for the entity.24 Essential for JPA
entity management.27
Example (See @Entity example above)
5.4. @GeneratedValue
The @GeneratedValue annotation specifies how the primary key value is automatically
generated.24 Common strategies include IDENTITY (database auto-increment),
SEQUENCE (database sequence), AUTO (provider choice).27
Example (See @Entity example above)
🔹 5.5. @Column
The @Column annotation defines attributes for the database column mapped to an
entity field, such as name, length, nullability, uniqueness, and column definition.24
🔹 Example:
🔹 Java
package [Link];
import [Link].*;
import [Link];
🔹 @Entity
@Table(name = "products")
public class Product {
🔹 @Id
@GeneratedValue(strategy = [Link])
private Long id;
@Column(name = "product_name", length = 100, nullable = false) // Custom column
name, length, not nullable
private String name;
@Column(unique = true) // Ensures this column value is unique in the table
private String sku;
@Column(columnDefinition = "TEXT") // Specify custom SQL type (database-dependent)
private String description;
@Column(updatable = false) // This column won't be included in SQL UPDATE
statements
private LocalDate createdDate;
🔹 @ManyToOne: Many instances of the current entity relate to one instance of another entity
(e.g., many Orders belong to one Customer). Often uses @JoinColumn for the foreign key.32,
47
🔹 @OneToMany: One instance of the current entity relates to many instances of another (e.g.,
one Customer has many Orders). Often uses mappedBy in bidirectional relationships.48, 49
🔹 @ManyToMany: Many instances relate to many others (e.g., many Students enroll in many
Courses). Typically uses @JoinTable.32
🔹 @OneToOne: One instance relates to exactly one other (e.g., one User has one UserProfile).
Can use @JoinColumn or shared primary key.33
🔹 Example:
🔹 Java
package [Link];
import [Link].*;
import [Link];
import [Link];
🔹 @Entity
🔹 // Getters, Setters...
}
🔹 // --- Order Entity ---
🔹 @Entity
@Table(name = "customer_orders")
public class Order {
@Id @GeneratedValue private Long id;
private [Link] orderDate;
// Many Orders belong to One Customer
@ManyToOne(fetch = [Link]) // LAZY is often preferred for performance
@JoinColumn(name = "customer_id", nullable = false) // Defines the foreign key column
private Customer customer;
🔹 // Getters, Setters...
}
🔹 @Entity
🔹 // Getters, Setters...
}
🔹 @Entity
}
🔹 @Entity
🔹 // Getters, Setters...
}
// --- UserProfile Entity ---
🔹 @Entity
🔹 // Getters, Setters...
}
5.7. @ElementCollection
Defines a one-to-many relationship to a collection of non-entity types (Embeddables or
basic types like String).34 Stores values in a separate collection table defined by
@CollectionTable.38, 50
🔹 Example:
🔹 Java
package [Link];
import [Link].*;
import [Link];
🔹 @Entity
🔹 // Getters, Setters...
}
@Embeddable // Address is not an entity, just a value object
public class Address {
private String street;
private String city;
private String zipCode;
🔹 // Getters, Setters...
}
🔹 5.8. @Embedded
Embeds an @Embeddable object's fields directly into the owning entity's table
columns.34 Use @AttributeOverride(s) to customize column names if needed.39
🔹 Example:
🔹 Java
package [Link];
import [Link].*;
🔹 @Entity
🔹 @Embedded
🔹 // Getters, Setters...
}
// Address class is the same @Embeddable class from the @ElementCollection example
🔹 5.9. @Embeddable
Marks a class as embeddable, meaning its instances are stored as part of an owning
entity and don't have their own lifecycle or primary key.34 Used with @Embedded or
@ElementCollection.34
Example (See Address class in @ElementCollection and @Embedded examples above)
🔹 5.10. @Query
Defines custom JPQL or native SQL queries directly on repository methods.25, 26 Use
@Param to bind method parameters to query parameters.26
🔹 Example:
🔹 Java
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
public interface UserRepository extends JpaRepository<User, Long> {
// Custom JPQL query with named parameters
🔹 @Modifying
package [Link];
public interface UserSummary {
String getUsername();
String getEmail();
}
5.11. @EnableJpaRepositories
Enables Spring Data JPA repository support, scanning specified packages for interfaces
extending JpaRepository (or other Spring Data repository interfaces) and creating
implementations.25, 26 Often implicitly enabled by Spring Boot auto-configuration
when spring-boot-starter-data-jpa is present.
🔹 Java
package [Link];
import [Link];
import [Link];
🔹 @Configuration
6.1. @ConfigurationProperties
Maps external configuration properties (from [Link]/yml) to fields of a
POJO.13 Specify a prefix to group related properties. Supports validation.13
🔹 Example:
🔹 [Link]:
🔹 Properties
🔹 [Link]=[Link]
[Link]=YOUR_API_KEY_HERE
[Link]-ms=5000
[Link]=true
🔹 Java Class:
🔹 Java
package [Link];
import [Link];
import [Link]; // Or use
@EnableConfigurationProperties
import [Link];
import [Link];
import [Link];
@Component // Makes it a bean eligible for property binding
@ConfigurationProperties(prefix = "[Link]") // Binds properties starting with
"[Link]"
@Validated // Enables validation on the fields
public class ApiProperties {
🔹 @Component
@ConfigurationProperties(prefix = "[Link]")
public class FeatureFlags {
private NewUI newUi = new NewUI(); // Nested object
public NewUI getNewUi() { return newUi; }
public void setNewUi(NewUI newUi) { [Link] = newUi; }
public static class NewUI { // Nested static class for properties
private boolean enabled;
public boolean isEnabled() { return enabled; }
public void setEnabled(boolean enabled) { [Link] = enabled; }
}
}
🔹 // --- Usage ---
package [Link];
import [Link];
import [Link];
import [Link];
🔹 @Service
🔹 @Autowired
}
// ... use properties
}
🔹 Example:
🔹 [Link]:
🔹 Properties
🔹 [Link]=[Link]
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
🔹 @Configuration
}
}
🔹 6.3. @Value
🔹 Example:
🔹 Java
package [Link];
import [Link];
import [Link];
🔹 @Component
🔹 @Value("${[Link].0.0}")
}
}
🔹 7. Testing Annotations
7.1. @SpringBootTest
Loads the full Spring ApplicationContext for integration tests, closely mimicking the
production environment.28 The webEnvironment attribute controls web server setup
(e.g., MOCK, RANDOM_PORT).30, 63
🔹 Example:
🔹 Java
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import static [Link];
// Loads the full application context
@SpringBootTest(webEnvironment = [Link]) // or
RANDOM_PORT, NONE etc.
class MyApplicationIntegrationTest {
@Autowired // Inject real beans from the context
private UserService userService;
🔹 @Autowired
🔹 @Test
void contextLoads() {
assertThat(context).isNotNull();
}
🔹 @Test
void userServiceShouldBeAvailable() {
assertThat(userService).isNotNull();
// Perform tests using the actual service bean
}
}
7.2. @WebMvcTest
Tests the Spring MVC web layer (controllers) in isolation.30 Instantiates only web-
related beans (controllers, filters, MVC infrastructure) and auto-configures MockMvc.30
Excludes service, repository, component beans unless explicitly included or mocked.30
🔹 Example:
🔹 Java
package [Link];
import [Link]; // Service dependency of the
controller
import [Link];
import [Link];
import [Link];
import [Link]; // To mock
dependencies
import [Link];
import static [Link];
import static
[Link];
import static
[Link];
import static
[Link];
// Test only ProductRestController, providing mocks for its dependencies
@WebMvcTest([Link])
class ProductRestControllerTest {
🔹 @Autowired
🔹 @Test
[Link](get("/api/products/{id}", productId))
.andExpect(status().isOk())
🔹 .andExpect(content().json("{\"id\":1,\"name\":\"Test Product\",\"price\":99.99}")); //
Assuming Product serializes like this
}
}
// Dummy Product class for example
class Product {
private Long id; private String name; private double price;
public Product(Long id, String name, double price) { [Link] = id; [Link] = name;
[Link] = price;}
// Getters needed for JSON serialization
public Long getId() { return id; } public String getName() { return name; } public double
getPrice() { return price; }
}
7.3. @DataJpaTest
Tests the persistence layer (JPA repositories) specifically.28 Configures an in-memory
database, JPA entities, and Spring Data repositories.28 Tests are transactional and rolled
back by default.28 Auto-configures TestEntityManager.28
🔹 Example:
🔹 Java
package [Link];
import [Link]; // The @Entity class
import [Link];
import [Link];
import [Link];
import [Link]; // For
setting up data
import static [Link];
@DataJpaTest // Configures in-memory DB, scans for @Entity, configures repositories
// By default, replaces real DB config with an embedded one (like H2)
class UserRepositoryTest {
🔹 @Autowired
🔹 @Autowired
🔹 @Test
void findByUsernameShouldReturnUser() {
assertThat(foundUser).isNotNull();
assertThat([Link]()).isEqualTo("testuser");
}
🔹 @Test
void saveShouldPersistUser() {
🔹 // Given
🔹 // When
🔹 // Then
assertThat(savedUser).isNotNull();
assertThat([Link]()).isNotNull(); // Should have an ID assigned
User retrievedUser = [Link]([Link], [Link]());
assertThat([Link]()).isEqualTo("newbie");
}
}
// Dummy User entity for example
@[Link] @[Link](name="users")
class User {
@[Link] @[Link] private Long id;
private String username; private String email;
public Long getId() { return id;} public String getUsername() { return username;} public
void setUsername(String u) {[Link]=u;}
public String getEmail() { return email; } public void setEmail(String e) {[Link]=e;}
}
7.4. @TestConfiguration
Defines extra beans or customizes configuration specifically for tests, often used within
a test class as a static inner class or imported via @Import.31 Avoids loading the full
application configuration.31
🔹 Example:
🔹 Java
package [Link];
import [Link]; // Assume this has real config
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link]; // To override real bean
import [Link];
@[Link]
class MyProcessingService {
private final ExternalServiceClient externalServiceClient;
public MyProcessingService(ExternalServiceClient client) { [Link] =
client;}
}
🔹 @Bean
@Primary // Make this the primary bean, overriding any real one
public ExternalServiceClient testExternalServiceClient() {
[Link]("Creating MOCK ExternalServiceClient for test!");
return new MockExternalServiceClient(); // Provide a mock or stub implementation
}
}
🔹 @Autowired
🔹 @Test
void serviceShouldUseTestBean() {
String result = [Link]();
[Link](result)
🔹 Example:
🔹 Java
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import static [Link];
// --- Component using properties ---
🔹 @Component
class PropertyReaderComponent {
@Value("${[Link]}") private boolean featureXEnabled;
@Value("${[Link]}") private String serviceUrl;
@SpringBootTest
// Load properties from a test file AND override specific properties inline
🔹 @TestPropertySource(locations = "classpath:[Link]",
🔹 @Autowired
🔹 @Test
void propertiesShouldBeOverridden() {
// Value from inline property override
assertThat([Link]()).isFalse();
// Value from inline property override (higher precedence than test file or default)
assertThat([Link]()).isEqualTo("Inline test message");
}
}
// --- [Link] (in src/test/resources) ---
🔹 // [Link]=[Link]
// [Link]=true <- This will be overridden by the inline property in the test
8.1. @EnableMethodSecurity
Enables method-level security using annotations like @PreAuthorize, @PostAuthorize,
@Secured, @RolesAllowed.65, 66 Replaces the older @EnableGlobalMethodSecurity.
Uses AuthorizationManager.66
🔹 Example:
🔹 Java
package [Link];
import [Link];
import [Link];
import
[Link]
curity;
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
🔹 @Configuration
🔹 @Bean
🔹 @Bean
return [Link]();
}
// RoleHierarchy bean can also be defined here if needed (see @RoleHierarchy example)
}
🔹 8.2. @Secured
Specifies a list of role names (must start with ROLE_ by convention) allowed to access a
method.22 Does not support SpEL.22 Requires securedEnabled = true in
@EnableMethodSecurity.
🔹 Example:
🔹 Java
package [Link];
import [Link];
import [Link];
🔹 @Service
🔹 Example:
🔹 Java
package [Link];
import [Link];
import [Link];
🔹 @Service
}
// Access based on username matching the method argument 'ownerUsername'
@PreAuthorize("#ownerUsername == [Link]")
public String getResourceForOwner(String resourceId, String ownerUsername) {
return "Resource " + resourceId + " data for " + ownerUsername;
}
// Access based on user having a specific permission for the resource ID
@PreAuthorize("@[Link](authentication,
#resourceId, 'READ')")
public String readResourceById(String resourceId) {
// Assumes a bean named 'permissionService' exists with the specified method
}
}
8.4. @PostAuthorize
Uses SpEL to enforce authorization after method execution, often based on the
method's return value.22 The returnObject variable is available in the expression.22
🔹 Example:
🔹 Java
package [Link];
import [Link];
import [Link];
import [Link]; // Assume Document has an 'owner'
field
🔹 @Service
🔹 Example:
🔹 Java
package [Link];
import [Link];
import [Link];
import [Link];
import [Link]; // Assume Item has an 'owner' field
🔹 @Service
}
}
// Example specifying filterTarget
@PreFilter(filterTarget = "itemIds", value = "hasAuthority('PROCESS_ID_' +
filterObject)")
public void processSpecificIds(List<String> itemIds, List<String> userPrefs) {
// Only itemIds for which the user has PROCESS_ID_{id} authority remain.
// userPrefs list remains unchanged.
}
}
// Dummy Item class
class Item {
public String name; public String owner;
public Item(String name, String owner) { [Link] = name; [Link] = owner;}
public String getName() {return name;}
}
8.6. @PostFilter
Filters a returned collection or array after method execution using SpEL.22 filterObject
refers to the current element in the returned collection.68 Be mindful of performance
with large collections.
🔹 Example:
🔹 Java
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link]; // Assume Report has 'isPublic' boolean field
🔹 @Service
🔹 Example:
🔹 Java
package [Link];
import [Link];
import [Link];
🔹 @Service
🔹 Example:
🔹 Java
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link]; // Example of a custom
principal
@RestController
public class UserInfoController {
// Inject the standard Spring Security UserDetails object
@GetMapping("/api/user/details")
public String getUserDetails(@AuthenticationPrincipal UserDetails userDetails) {
if (userDetails != null) {
}
return "User not authenticated.";
}
// Inject a custom UserDetails implementation (if configured)
@GetMapping("/api/user/custom-info")
public String getCustomUserInfo(@AuthenticationPrincipal CustomUserDetails
customUser) {
if (customUser != null) {
}
return "User not authenticated or not a CustomUserDetails instance.";
}
// Inject just the username (String) if configured appropriately or using SpEL
@GetMapping("/api/user/name")
public String getUsername(@AuthenticationPrincipal(expression = "username") String
username) {
}
}
// Dummy CustomUserDetails for example
// import [Link];
// public class CustomUserDetails extends User {
// private final Long userId; private final String email;
// public CustomUserDetails(...) { /* constructor */ }
// public Long getUserId() { ... } public String getEmail() { ... }
// }
8.9. @RoleHierarchy
Used in configuration (typically on a @Bean method returning RoleHierarchy) to define
relationships between roles (e.g., ADMIN > MANAGER > USER).77 Access decisions using
hasRole or similar in SpEL will then respect this hierarchy.
🔹 Java
package [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import
[Link]
curity;
🔹 @Configuration
🔹 @Bean
🔹 @Service
🔹 9. Conclusion
This report has provided a comprehensive overview, complete with examples, of the
most commonly used annotations in Spring Boot applications, categorized by their
functionalities. These annotations play a vital role in simplifying and enhancing various
aspects of Spring Boot development, from core application setup and bean
management to REST API creation, data persistence with JPA, property configuration,
testing, and security implementation. The declarative nature of annotations reduces
boilerplate code, improves code readability, and empowers developers to build
sophisticated applications with greater efficiency and maintainability. Understanding
and effectively utilizing these annotations, aided by practical examples, is fundamental
for any developer working with the Spring Boot framework.