classafIoc::RegistryBuilder
sys::Obj afIoc::RegistryBuilder
@
Js
Use to create an IoC Registry.
Add module classes, scopes, services, and contributions.
- addModule
Adds a module to the registry. The given
module
may be:- a module instance,
- a module
Type
- a qualified module name (
Str
) - a pod name (
Str
) null
(does nothing)
If a pod name then dependencies are also added.
Any modules defined with the
@SubModule
facet are also added.Don't forget you can always call
removeModule(...)
too!- addModules
This addModules(Obj[] modules)
Adds many modules to the registry.
- addModulesFromPod
This addModulesFromPod(Str podName, Bool addDependencies := true)
Inspects the pod's meta-data for the key
afIoc.module
. This is then treated as a CSV list of (qualified) module type names to load.If
addDependencies
istrue
then the pod's dependencies are also inspected for IoC modules.- addScope
ScopeBuilder addScope(Str scopeId, Bool threaded := true)
Defines a new scope to be used with the registry.
regBuilder.addScope("thread")
- addService
ServiceBuilder addService(Type? serviceType := null, Type? serviceImplType := null)
Defines a new service to be added to the registry.
regBuilder.addService(Penguin#).withId("penguins").withScope("root")
Note if
serviceType
is a mixin then, if none given, the builder looks for an implementation class named the same as the mixin but with anImpl
suffix.Hence:
regBuilder.addService(Penguins#, PenguinsImpl#)
is the same as:
regBuilder.addService(Penguins#)
- build
Registry build()
Builds and returns the registry; this may only be done once.
- contributeToService
This contributeToService(Str serviceId, |Configuration configFunc, Bool optional := false)
Lets you contribute to a service configuration via its ID.
regBuilder.contributeToService("acme::Penguins") |Configuration config| { config["food"] = Fish() }
The service ID you're contributing to has to exist. If the service may, or may not exist, (for example, if you're contributing to an optional 3rd party library) then you may mark the contribution as optional. That way, no Err is thrown should the service not exist.
regBuilder.contributeToService("acme::Penguins", |Configuration config| { config["food"] = Fish() }, true)
- contributeToServiceType
This contributeToServiceType(Type serviceType, |Configuration configFunc, Bool optional := false)
Lets you contribute to a service configuration by its Type.
regBuilder.contributeToServiceType(Penguins#) |Configuration config| { config["food"] = Fish() }
- decorateService
This decorateService(Str serviceGlob, |Configuration decoratorHook)
Allows you to decorate / replace services with your own implementations.
regBuilder.decorateService("acme::MyService") |Configuration config| { config["alt-1"] = |Obj? serviceInstance, Scope scope, ServiceDef serviceDef->Obj?| { return MyServiceAlt(serviceInstance) } }
Where
scopeGlob
is a not a service ID, but a regex glob that is used to match against service IDs and their aliases.The difference between decorating and overriding, is that when decorating you are passed the original instance. This makes it perfect for wrapping implementations with logging methods, or other cross cutting / AOP style operations.
- onRegistryShutdown
This onRegistryShutdown(|Configuration shutdownHook)
Hook for executing funcs when the Registry shuts down.
regBuilder.onRegistryShutdown |Configuration config| { config["log.bye1"] = |Scope rootScope| { penguin := rootScope.serviceById("acme::Penguin") Log.get("afIoc").info("Goodbye ${penguin.name}!") } }
Note that the root scope is always passed into shutdown funcs.
An alternative to this method is to use an
AppModule
method namedonRegistryShutdown()
, the advantage of which is that the arguments are dependency resolved.Void onRegistryShutdown(Configuration config, Penguin penguin) { config.set("log.bye2", |Scope rootScope| { Log.get("afIoc").info("Goodbye ${penguin.name}!") }).after("log.bye1") }
Or, if you don't care about ordering, you may omit the call to
Configuration
:Void onRegistryShutdown(Penguin penguin) { Log.get("afIoc").info("Goodbye ${penguin.name}!") }
- onRegistryStartup
This onRegistryStartup(|Configuration startupHook)
Hook for executing funcs when the Registry starts up.
regBuilder.onRegistryStartup |Configuration config| { config["log.hello1"] = |Scope rootScope| { penguin := rootScope.serviceById("acme::Penguin") Log.get("afIoc").info("Hello ${penguin.name}!") } }
Note that the root scope is always passed into startup funcs.
An alternative to this method is to use an
AppModule
method namedonRegistryStartup()
, the advantage of which is that the arguments are dependency resolved.Void onRegistryStartup(Configuration config, Penguin penguin) { config.set("log.hello2", |Scope rootScope| { Log.get("afIoc").info("Hello ${penguin.name}!") }).after("log.hello1") }
Or, if you don't care about ordering, you may omit the call to
Configuration
:Void onRegistryStartup(Penguin penguin) { Log.get("afIoc").info("Hello ${penguin.name}!") }
- onScopeCreate
This onScopeCreate(Str scopeGlob, |Configuration createHook)
Hook for executing funcs when a scope is created.
regBuilder.onScopeCreate("ro*") |Configuration config| { config["log.hello"] = |Scope scope| { Log.get("afIoc").info("BEGIN ${scope.id}") } }
Where
scopeGlob
is a not a scope ID, but a regex glob that is used to match against scope IDs and their aliases.- onScopeDestroy
This onScopeDestroy(Str scopeGlob, |Configuration destroyHook)
Hook for executing funcs when a scope is created.
regBuilder.onScopeDestroy("ro*") |Configuration config| { config["log.bye"] = |Scope scope| { Log.get("afIoc").info("END ${scope.id}") } }
Where
scopeGlob
is a not a scope ID, but a regex glob that is used to match against scope IDs and their aliases.- onServiceBuild
This onServiceBuild(Str serviceGlob, |Configuration buildHook)
Hook for executing funcs when a service is created.
regBuilder.onServiceBuild("*penguin*") |Configuration config| { config["log.hello"] = |Obj? instance, Scope scope, ServiceDef def| { Log.get("afIoc").info("HELLO WORLD from ${def.id}") } }
Where
scopeGlob
is a not a service ID, but a regex glob that is used to match against service IDs and their aliases.Note there is also a hook available for when class is autobuilt - see the src for
AutoBuilder
for details.- options
Str:Obj? options := ... { private set }
Use options to pass state into the IoC Registry. This map may be later retrieved from the RegistryMeta service.
- overrideService
ServiceOverrideBuilder overrideService(Str serviceId)
Override values in an existing service definition.
The given id may be a service id to override a service, or an override id to override an override.
regBuilder.addService(Penguins#).withCtorArgs(["fishLegs"]) regBuilder.overrideService(Penguins#.qname).withCtorArgs(["fishHands"])
- overrideServiceType
ServiceOverrideBuilder overrideServiceType(Type serviceType)
Override values in an existing service definition.
regBuilder.addService(Penguins#).withCtorArgs(["fishLegs"]) regBuilder.overrideServiceType(Penguins#).withCtorArgs(["fishHands"])
- removeModule
This removeModule(Type? moduleType)
Removes modules of the given type. If a module of the given type is subsequently added, it is silently ignored.
- setOption
This setOption(Str name, Obj? value)
Sets a value in the
options
map. Returnsthis
so it may be used as a builder method.- silent
This silent()
Suppresses surplus logging by
RegistryBuilder
andRegistry
.Removes the following contributions from registry startup:
afIoc.logBanner
afIoc.logServices
And the following from registry shutdown:
afIoc.sayGoodbye