Inject a Logger dependency into a component's field using the ! suffix.
← Dependency Injection · Ref: Q1112
Declare injection fields with the ! suffix:
MessageService is Service logger as Logger!
The compiler validates at compile time that a matching registration exists. Only abstract component types can be injection targets.
See Q1110 for register/inject basics. See Q227 for compile-time validation.
Example
defines module qa.di.fieldinjection defines component Logger as abstract log() as abstract -> message as String <- output as String? default operator ? ConsoleLogger is Logger override log() -> message as String <- output as String: `[INFO] ${message}` default operator ? Service as abstract send() as abstract -> message as String <- result as String? default operator ? //logger field is injected via ! suffix MessageService is Service logger as Logger! override send() -> message as String <- result <- String() result: logger.log(message) default operator ? defines application FieldInjectionApp register ConsoleLogger() as Logger register MessageService() as Service defines program FieldInjectionDemo() with application of FieldInjectionApp stdout <- Stdout() service as Service! result <- service.send("Hello from DI") stdout.println(result)
Common mistakes
E08150 — Injection fields must use abstract types. Inject the abstraction (Logger), not the concrete implementation (ConsoleLogger).
Incorrect:
logger as ConsoleLogger!
Correct:
logger as Logger!
Other ways to ask this
- I need a MessageService component that gets its Logger from the DI container
- In Spring I'd use @Autowired on a field. Show the EK9 field injection pattern
- Given a service component, declare an injection field with the ! suffix
- Wire a Logger into a MessageService component through field injection
Coming from another language?
Spring: @Autowired private Logger logger. Guice: @Inject Logger logger. EK9: logger as Logger! — the ! suffix marks injection.
Keywords: component, autowired, inject, !, dependency, field