@Profile

@Profile([...]) registers a bean only when the active profiles match.

Why

Profiles name the situations an application runs in: dev, test, prod, eu. They are activated with the spring.profiles.active property or Environment.setActiveProfiles.

Use @Profile to swap implementations between them: an in-memory mailer during development, a fake payment gateway in tests, the real ones in production. No if in main, and no test-only code path in the services.

Each entry is a profile expression:

The bean is registered when any entry matches. On a configuration class, the profile applies to all its @Bean methods and to its @PropertySource files.

To name a set of profiles once, subclass Profile:

class Dev extends Profile {
  const Dev() : super(const ['dev']);
}

Example

import 'package:spring_core_dart/spring_core_dart.dart';

abstract interface class Mailer {
  void send(String to, String text);
}

const log = SpringLog('mail');

// Development and tests: mails go to the log, nobody gets real mail.
@Component()
@Profile(['dev', 'test'])
class LogMailer implements Mailer {
  @override
  void send(String to, String text) => log.info('mail to $to: $text');
}

// Everywhere else.
@Component()
@Profile(['!dev & !test'])
class SmtpMailer implements Mailer {
  @override
  void send(String to, String text) {
    // talk to the SMTP server
  }
}

Activating a profile without Spring Boot:

void main() {
  final env = StandardEnvironment()..setActiveProfiles(['dev']);
  final context = ApplicationContext.run([appBeans], environment: env);
  context.getBean<Mailer>().send('[email protected]', 'Hi'); // LogMailer
  context.close();
}

With configuration files, spring.profiles.active=dev in application.properties does the same.

Parameters

Name Type Default Meaning
value (positional) List<String> required Profile expressions. The bean is registered if any of them matches.

In Spring (Java)

@Component
@Profile({"dev", "test"})
class LogMailer implements Mailer { ... }

Differences that matter:

See also