0
# Context-Free Wiring
1
2
Context-free wiring with `autowire` creates instances using explicitly provided dependencies, without relying on the surrounding context. This approach is only available in Scala 3 and provides maximum flexibility in dependency specification.
3
4
## Core Functions
5
6
### autowire
7
8
Creates an instance of type `T` using provided dependencies. Missing dependencies are automatically created using public constructors or companion object `apply` methods.
9
10
```scala { .api }
11
inline def autowire[T](inline dependencies: Any*): T
12
```
13
14
**Parameters:**
15
- `dependencies: Any*` - Variable number of dependency specifications
16
17
**Returns:** Instance of type `T` with all dependencies wired
18
19
**Dependency Types:**
20
Each dependency parameter can be:
21
- **Instance**: Direct instance to use for injection
22
- **Function**: Function that creates an instance when called
23
- **Class**: `classOf[SomeType]` to instantiate the class for dependency types it implements
24
25
26
## Usage Examples
27
28
### Basic Autowiring
29
30
```scala
31
import com.softwaremill.macwire.*
32
33
class DatabaseAccess()
34
class SecurityFilter()
35
class UserFinder(databaseAccess: DatabaseAccess, securityFilter: SecurityFilter)
36
class UserStatusReader(userFinder: UserFinder)
37
38
// Creates all dependencies automatically
39
val userStatusReader = autowire[UserStatusReader]()
40
```
41
42
Generates equivalent code:
43
```scala
44
val userStatusReader = {
45
val wiredDatabaseAccess = new DatabaseAccess()
46
val wiredSecurityFilter = new SecurityFilter()
47
val wiredUserFinder = new UserFinder(wiredDatabaseAccess, wiredSecurityFilter)
48
val wiredUserStatusReader = new UserStatusReader(wiredUserFinder)
49
wiredUserStatusReader
50
}
51
```
52
53
### Providing Instance Dependencies
54
55
```scala
56
import java.io.Closeable
57
58
class DataSource(jdbcConn: String) extends Closeable { def close() = () }
59
class DatabaseAccess(ds: DataSource)
60
class UserFinder(databaseAccess: DatabaseAccess)
61
62
// Provide pre-configured DataSource instance
63
val dataSource = new DataSource("jdbc:postgresql://localhost/mydb")
64
val userFinder = autowire[UserFinder](dataSource)
65
```
66
67
### Using Factory Functions
68
69
```scala
70
class ConfiguredService(config: Config)
71
72
// Use function to create dependency
73
val createService = () => new ConfiguredService(loadConfig())
74
val someService = autowire[SomeServiceUsingConfiguredService](createService)
75
```
76
77
### Using Class Dependencies
78
79
```scala
80
trait Logger
81
class ConsoleLogger extends Logger
82
class FileLogger extends Logger
83
class Service(logger: Logger)
84
85
// Specify which Logger implementation to use
86
val service = autowire[Service](classOf[ConsoleLogger])
87
```
88
89
90
### Complex Dependency Scenarios
91
92
```scala
93
class EmailService(smtpHost: String, port: Int)
94
class NotificationService(emailService: EmailService, logger: Logger)
95
class UserService(notificationService: NotificationService)
96
97
class AppConfig {
98
val smtpHost = "smtp.example.com"
99
val smtpPort = 587
100
val logger = new ConsoleLogger()
101
}
102
103
val appConfig = new AppConfig()
104
105
// Combine multiple dependency sources
106
val userService = autowire[UserService](
107
appConfig.smtpHost,
108
appConfig.smtpPort,
109
appConfig.logger
110
)
111
```
112
113
## Behavior and Characteristics
114
115
### Dependency Resolution Order
116
117
1. **Explicit Dependencies**: Parameters passed to `autowire` are checked first
118
2. **Constructor/Apply Methods**: Missing dependencies are created using public constructors or companion object `apply` methods
119
3. **Recursive Creation**: The process repeats for nested dependencies
120
121
### Type Matching
122
123
- Dependencies are matched by exact type
124
- Subtype relationships are not automatically resolved
125
- Generic types are matched with full type parameters
126
127
### Error Conditions
128
129
- **Missing Dependencies**: Compile-time error if a required dependency cannot be created or provided
130
- **Ambiguous Dependencies**: Error when multiple instances of the same type are provided
131
- **Unsupported Types**: Primitive types and certain Scala built-in types cannot be autowired
132
- **Cyclic Dependencies**: Detected and reported at compile time
133
134
### Compilation Requirements
135
136
- Only available in Scala 3
137
- Requires the macros library as a "provided" dependency
138
- All wiring resolution happens at compile time with zero runtime overhead