Conditional Beans with @Profile & Production Patterns
Master conditional Spring bean registration using @Profile, resolving bean ambiguity, implementation switching, and production configuration anti-patterns.
Conditional Beans with @Profile & Production Patterns
While profile-specific configuration files change property values, the @Profile annotation changes which Spring Beans are instantiated in the ApplicationContext.
1. Values vs Implementations: The Critical Decision Rule
CRITICAL DECISION RULE:
├── Different Property Values? ──► Use Profile Files (application-dev.yml vs application-prod.yml)
└── Different Java Classes? ──► Use @Profile Annotation (@Profile("dev") vs @Profile("prod"))2. Conditional Bean Creation with @Profile
Suppose an application sends notifications. In development, notifications should be logged to the console without sending real emails. In production, real emails must be dispatched via SMTP:
Common Service Interface
public interface NotificationService {
void sendNotification(String recipient, String message);
}1. Development Implementation (@Profile("dev"))
@Service
@Profile("dev")
public class DevNotificationService implements NotificationService {
@Override
public void sendNotification(String recipient, String message) {
System.out.println("[DEV MOCK NOTIFICATION] To: " + recipient + " | Msg: " + message);
}
}2. Production Implementation (@Profile("prod"))
@Service
@Profile("prod")
public class ProdNotificationService implements NotificationService {
@Override
public void sendNotification(String recipient, String message) {
// Dispatch real email via SMTP
System.out.println("[PROD SMTP EMAIL] Dispatched to: " + recipient);
}
}3. How @Profile Prevents Bean Ambiguity
Without @Profile, registering both DevNotificationService and ProdNotificationService as @Service beans would cause Spring DI to fail with NoUniqueBeanDefinitionException due to candidate ambiguity.
With @Profile:
- When
SPRING_PROFILES_ACTIVE=dev, onlyDevNotificationServiceis registered inApplicationContext. - When
SPRING_PROFILES_ACTIVE=prod, onlyProdNotificationServiceis registered inApplicationContext.
@RestController
@RequestMapping("/api/notifications")
public class NotificationController {
private final NotificationService service;
// Zero ambiguity! Exactly ONE NotificationService implementation exists for the active profile
public NotificationController(NotificationService service) {
this.service = service;
}
@PostMapping
public String notifyUser(@RequestParam String email, @RequestParam String msg) {
service.sendNotification(email, msg);
return "Notification processed";
}
}4. Production Anti-Patterns Matrix
| Anti-Pattern | Operational Risk | Recommended Solution |
|---|---|---|
| 1. Hardcoding Active Profile in Source | Packages spring.profiles.active=prod into application.yml, making JAR non-reusable | Activate profiles externally via SPRING_PROFILES_ACTIVE |
2. Mixing .properties and .yml | Overlapping files create unpredictable property override bugs | Standardize strictly on application.yml |
3. Using @Profile for Value Changes | Creating separate classes just to change DB URLs or ports | Use application-dev.yml for values; @Profile for code |
4. Excessive Individual @Value Fields | Creates bloated, fragile classes with repeated annotations | Use @ConfigurationProperties for grouped settings |
❓ Interactive Self-Assessment
What is the difference between profile-specific files (application-dev.yml) and the @Profile annotation?
Designing One Reusable JAR for Multi-Environment Deployments
An enterprise system requires:
- Local Dev: Uses MySQL
localhost:3306/dev_dbon port8081with a mockDevPaymentService. - Production: Uses Cloud MySQL
prod-db:3306/prod_dbon port8080with a realStripePaymentService. - The Java Controller must remain 100% unchanged across both environments.
Design the file layout and Java implementation structure.
Profile-Specific Configuration & Activation
Master Spring profiles, profile-specific files (application-dev.yml, application-prod.yml), activation mechanisms, and build-once-deploy-anywhere principles.
Servlet Filter Fundamentals & Lifecycle
Master Servlet Filters in Spring Boot, the Security Checkpoint mental model, request pipeline execution, lifecycle methods, and Spring Boot 3 namespace rules.