Chapter 1: Core Spring Annotations
1. @SpringBootApplication
The startup annotation that combines three annotations into one.
@SpringBootApplication
public class MonApplication {
public static void main(String[] args) {
SpringApplication.run(MonApplication.class, args);
}
}
Equivalent to:
@SpringBootConfiguration // Indicates a configuration class
@EnableAutoConfiguration // Enables Spring Boot auto-configuration
@ComponentScan // Scans components in the current package and sub-packages
2. Stereotype Annotations
These annotations identify the role of a class in the architecture.
@Component
Generic annotation for any Spring bean.
@Component
public class EmailValidator {
public boolean isValid(String email) {
return email != null && email.contains("@");
}
}
@Service
Indicates a business logic class (service layer).
@Service
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public User findById(Long id) {
return userRepository.findById(id)
.orElseThrow(() -> new RuntimeException("User not found"));
}
}
@Repository
Indicates a data access class. Enables automatic translation of SQL exceptions into Spring exceptions.
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByEmail(String email);
}
@Controller
Indicates an MVC controller (returns HTML views).
@Controller
public class PageController {
@GetMapping("/accueil")
public String accueil(Model model) {
model.addAttribute("message", "Welcome!");
return "accueil"; // Returns the name of a view (template)
}
}
@RestController
Combination of @Controller + @ResponseBody. Each method returns JSON/XML directly.
@RestController
@RequestMapping("/api/users")
public class UserController {
@GetMapping
public List<User> getAll() {
return userService.findAll(); // Returns JSON automatically
}
}
Stereotype Summary
| Annotation | Layer | Role |
|---|---|---|
@Component | Generic | Any Spring bean |
@Service | Service | Business logic |
@Repository | Data | Database access |
@Controller | Web | MVC Controller (views) |
@RestController | Web | REST Controller (JSON) |
3. Dependency Injection Annotations
@Autowired
Automatic injection of a Spring bean.
@Service
public class OrderService {
// Constructor injection (RECOMMENDED)
private final ProductService productService;
@Autowired // Optional if only one constructor
public OrderService(ProductService productService) {
this.productService = productService;
}
}
@Service
public class NotificationService {
// Field injection (not recommended but common)
@Autowired
private EmailService emailService;
// Setter injection
@Autowired
public void setEmailService(EmailService emailService) {
this.emailService = emailService;
}
}
Always prefer constructor injection. It makes dependencies explicit and facilitates testing.
@Qualifier
Resolves ambiguities when multiple beans implement the same interface.
public interface NotificationSender {
void send(String message);
}
@Component("emailSender")
public class EmailNotification implements NotificationSender {
public void send(String message) { /* send email */ }
}
@Component("smsSender")
public class SmsNotification implements NotificationSender {
public void send(String message) { /* send SMS */ }
}
@Service
public class AlertService {
private final NotificationSender sender;
public AlertService(@Qualifier("emailSender") NotificationSender sender) {
this.sender = sender;
}
}
@Primary
Defines the default bean when multiple candidates exist.
@Primary
@Component
public class EmailNotification implements NotificationSender {
// This bean will be injected by default
}
@Value
Injects values from configuration files.
@Service
public class AppConfig {
@Value("${app.name}")
private String appName;
@Value("${app.max-retry:3}") // Default value = 3
private int maxRetry;
@Value("${server.port}")
private int port;
@Value("#{2 + 3}") // SpEL (Spring Expression Language)
private int calculated;
}
# application.yml
app:
name: MyApplication
max-retry: 5
server:
port: 8080
@Lazy
Delays bean initialization until its first use.
@Service
@Lazy
public class HeavyService {
public HeavyService() {
// This constructor will only be called when the bean is used
}
}
4. Configuration Annotations
@Configuration
Declares a Spring configuration class (XML equivalent).
@Configuration
public class AppConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
@Bean
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
return mapper;
}
}
@Bean
Declares a bean managed by the Spring container. Used in @Configuration classes.
@Configuration
public class SecurityConfig {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public AuthenticationManager authManager(AuthenticationConfiguration config)
throws Exception {
return config.getAuthenticationManager();
}
}
@ConfigurationProperties
Binds a group of properties to a Java object.
@Configuration
@ConfigurationProperties(prefix = "app.mail")
public class MailProperties {
private String host;
private int port;
private String username;
private String password;
// Getters and setters required
public String getHost() { return host; }
public void setHost(String host) { this.host = host; }
// ...
}
# application.yml
app:
mail:
host: smtp.gmail.com
port: 587
username: user@gmail.com
password: secret
@PropertySource
Loads an additional properties file.
@Configuration
@PropertySource("classpath:custom-config.properties")
public class CustomConfig {
@Value("${custom.property}")
private String customProp;
}
@Import
Imports other configuration classes.
@Configuration
@Import({SecurityConfig.class, DatabaseConfig.class})
public class AppConfig {
}
5. Scope and Lifecycle Annotations
@Scope
Defines the scope of the bean.
@Component
@Scope("prototype") // New instance for each injection
public class ShoppingCart {
private List<Item> items = new ArrayList<>();
}
| Scope | Description |
|---|---|
singleton | A single instance (default) |
prototype | New instance for each request |
request | One instance per HTTP request |
session | One instance per HTTP session |
application | One instance per ServletContext |
@PostConstruct
Executes a method after all dependencies have been injected.
@Service
public class CacheService {
private Map<String, Object> cache;
@PostConstruct
public void init() {
cache = new HashMap<>();
// Load initial data
}
}
@PreDestroy
Executes a method before the bean is destroyed.
@Service
public class ConnectionPool {
@PreDestroy
public void cleanup() {
// Close all connections
}
}
6. Profile and Conditional Annotations
@Profile
Activates a bean only for certain profiles.
@Configuration
@Profile("dev")
public class DevDatabaseConfig {
@Bean
public DataSource dataSource() {
// In-memory H2 for development
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.build();
}
}
@Configuration
@Profile("prod")
public class ProdDatabaseConfig {
@Bean
public DataSource dataSource() {
// PostgreSQL for production
HikariDataSource ds = new HikariDataSource();
ds.setJdbcUrl("jdbc:postgresql://localhost:5432/mydb");
return ds;
}
}
# Activate a profile
java -jar app.jar --spring.profiles.active=prod
@ConditionalOnProperty
Activates a bean based on the value of a property.
@Configuration
@ConditionalOnProperty(name = "app.feature.email", havingValue = "true")
public class EmailConfig {
@Bean
public EmailService emailService() {
return new SmtpEmailService();
}
}
@ConditionalOnClass
Activates a bean if a class is present in the classpath.
@Configuration
@ConditionalOnClass(name = "org.postgresql.Driver")
public class PostgresConfig {
// Automatically configured if the PostgreSQL driver is available
}
@ConditionalOnMissingBean
Activates a bean only if no other bean of the same type exists.
@Bean
@ConditionalOnMissingBean
public ObjectMapper objectMapper() {
return new ObjectMapper();
}
7. Lombok Annotations (Bonus)
Lombok automatically generates code at compile time.
@Data
Generates getters, setters, toString, equals, hashCode.
@Data
public class UserDto {
private Long id;
private String name;
private String email;
}
@Getter / @Setter
@Getter @Setter
public class Product {
private Long id;
private String name;
private BigDecimal price;
}
@NoArgsConstructor / @AllArgsConstructor / @RequiredArgsConstructor
@NoArgsConstructor
@AllArgsConstructor
public class Address {
private String street;
private String city;
private String zipCode;
}
@RequiredArgsConstructor // Constructor for final fields
@Service
public class UserService {
private final UserRepository userRepository; // Automatically injected
private final PasswordEncoder passwordEncoder;
}
@Builder
Implements the Builder pattern.
@Builder
@Data
public class UserDto {
private Long id;
private String name;
private String email;
}
// Usage
UserDto user = UserDto.builder()
.id(1L)
.name("Jean")
.email("jean@example.com")
.build();
@Slf4j
Automatically adds an SLF4J logger.
@Slf4j
@Service
public class PaymentService {
public void processPayment(Payment payment) {
log.info("Processing payment: {}", payment.getId());
log.debug("Amount: {}", payment.getAmount());
}
}
Quick Summary
| Annotation | Role |
|---|---|
@SpringBootApplication | Application entry point |
@Component | Generic bean |
@Service | Service layer (business logic) |
@Repository | Data layer (DB access) |
@Controller | MVC Controller |
@RestController | REST Controller |
@Autowired | Dependency injection |
@Qualifier | Bean selection for injection |
@Value | Config value injection |
@Configuration | Configuration class |
@Bean | Manual bean declaration |
@ConfigurationProperties | Property binding |
@Profile | Profile-based activation |
@PostConstruct | Initialization after injection |
@PreDestroy | Cleanup before destruction |
➡️ Chapter 2: Web and REST Annotations