How to use IOC

Overview

IoC means Inversion of Control. It’s a common design principle, and SmartActors, as many other popular frameworks, has it’s own IoC container.

The access to IoC is done through static service locator called IOC The main methods are void IOC.register(IKey key, IResolveDependencyStrategy strategy) and T IOC.resolve(IKey<T> key, Object... args). The container resolves objects by the IKey. The object resolving is delegated to a IResolveDependencyStrategy. There are a couple of predefined strategies.

Key

First of all, you need a key to register your strategy and resolve objects. The simplest way is to use the new operator.

IKey<MyClass> myNewKey = new Key<>("myKey");

If your strategy requires more type validation of the resolving objects, you can pass the Class to the key.

IKey<MyClass> myTypedKey = new Key<>(MyClass.class, "myKey");

However, the recommended way to get the key is to resolve it with IOC.

IKey<MyClass> myResolveKey = IOC.resolve(IOC.getKeyForKeyStorage(), "myKey");

IOC.getKeyForKeyStorage() produces the key to get the key.

This magic is hidden in Keys class, so it’s necessary just to call Keys.getOrAdd().

IKey<MyClass> myKey = Keys.getOrAdd("myKey");

Initialization

To resolve the key, the corresponding strategy should be registered before. Also, the default IoC implementation requires the Scope to be initialized. So this initialization code is required (usually it’s already called by the server implementation):

Object scopeKey = ScopeProvider.createScope(null);
IScope scope = ScopeProvider.getScope(scopeKey);
ScopeProvider.setCurrentScope(scope);
scope.setValue(IOC.getIocKey(), new StrategyContainer());
IOC.register(IOC.getKeyForKeyStorage(), new ResolveByNameIocStrategy(
        (a) -> new Key((String) a[0]))
);

The ResolveByNameIocStrategy it responsive to create Keys by the name as it was demonstrated above.

Singleton strategy

When you have a key, you can register the resolving strategy. For example, SingletonStrategy:

IKey<MyClass> key = Keys.getOrAdd("singleton");
MyClass myObject = new MyClass("singleton");
IOC.register(key, new SingletonStrategy(myObject));

This strategy always returns the same object instance, given to it’s constructor.

MyClass resolveObject1 = IOC.resolve(key);
MyClass resolveObject2 = IOC.resolve(key);

Both these variables point to the same object.

New instance strategy

The CreateNewInstanceStrategy creates a new object for each call to resolve(). You should define a lambda expressions to create your objects and pass it to the strategy constructor.

IKey<MyClass> key = Keys.getOrAdd("new");
IOC.register(key, new CreateNewInstanceStrategy(
        (args) -> new MyClass((String) args[0])));

Then you can resolve instances of your class.

MyClass resolveObject1 = IOC.resolve(key, "id1");
MyClass resolveObject2 = IOC.resolve(key, "id1");
MyClass resolveObject3 = IOC.resolve(key, "id3");

All returned objects are different objects. However, these objects can be equal (but not the same) if you pass the same parameters to the resolve() method (string id in this example).