classafIoc::RegistryBuilder

sys::Obj
  afIoc::RegistryBuilder

@Js

Use to create an IoC Registry.

Add module classes, scopes, services, and contributions.

addModule

Source

This addModule(Obj? module)

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

Source

This addModules(Obj[] modules)

Adds many modules to the registry.

addModulesFromPod

Source

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 is true then the pod's dependencies are also inspected for IoC modules.

addScope

Source

ScopeBuilder addScope(Str scopeId, Bool threaded := true)

Defines a new scope to be used with the registry.

regBuilder.addScope("thread")
addService

Source

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 an Impl suffix.

Hence:

regBuilder.addService(Penguins#, PenguinsImpl#)

is the same as:

regBuilder.addService(Penguins#)
build

Source

Registry build()

Builds and returns the registry; this may only be done once.

contributeToService

Source

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

Source

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

Source

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

Source

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 named onRegistryShutdown(), 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

Source

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 named onRegistryStartup(), 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

Source

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

Source

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

Source

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

Source

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

Source

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

Source

ServiceOverrideBuilder overrideServiceType(Type serviceType)

Override values in an existing service definition.

regBuilder.addService(Penguins#).withCtorArgs(["fishLegs"])
regBuilder.overrideServiceType(Penguins#).withCtorArgs(["fishHands"])
removeModule

Source

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

Source

This setOption(Str name, Obj? value)

Sets a value in the options map. Returns this so it may be used as a builder method.

silent

Source

This silent()

Suppresses surplus logging by RegistryBuilder and Registry.

Removes the following contributions from registry startup:

  • afIoc.logBanner
  • afIoc.logServices

And the following from registry shutdown:

  • afIoc.sayGoodbye