Class BeanContext
java.lang.Object
com.tccc.kos.commons.core.context.BeanContext
System component that provides a very lightweight IOC-style context. It supports
"phased autowiring", which allows beans to autowire a bit at a time for controlled
startup, without having to worry about circular dependencies and such.
It also supports asynchronous ready infrastructure, which allows the context
to pause while beans asynchronously warm up, at which point the context can
continue moving forward. It also provides autowiring support for
ListenerList
objects, so that any beans that implement an interface of any ListenerList
property will automatically be added to the listener list, even if added
after the fact.
This is unique relative to standard web-style IOC containers, as we're booting an operating system which has a lot of phased steps and asynchronous processes which need to be coordinated as part of bringing up the system, which means we need a richer set of functionality. That said, this is very compact and caters only to the specific needs of kOS.
Use this object to perform dependency injection (auto-wire) on all program objects. Typical application startup looks like the following.
// Instantiate all of your program objects
// (analogous to Spring creating all @Component, @Service, and @Controller objects)
Foo foo = new Foo();
Bar bar = new Bar();
Baz baz1 = new Baz();
Baz baz2 = new Baz();
// Create the runtime context (analogous to Spring's application context)
RuntimeContext ctx = new RuntimeContext();
// Add all instantiated beans (from above) to this runtime context:
ctx.add(foo); // unnamed objects
ctx.add(bar);
ctx.add("baz1", baz1); // named objects (because there are multiple of the same type)
ctx.add("baz2", baz2);
// Populate all @Autowired fields whose phase is "one":
ctx.update("one");
// Populate all @Autowired fields whose phase is "two":
ctx.update("two");
// Populate all remaining @Autowired fields that do not specify a phase:
// (This is the last update() call; any further calls result in an exception)
ctx.update(null);
// At this point, all beans (and listeners) are created and auto-wired.
// However, you can connect another bean by using the connect() method:
ctx.connect("hey", new Hey());
// To retrieve a bean, there are two methods.
// One takes a name, and the other doesn't:
Baz bazBean = ctx.getBean("baz1", Baz.class);
Foo fooBean = ctx.getBean(Foo.class);
// A list of beans of the same type can also be retrieved:
List<Baz> bazList = ctx.getBeans(Baz.class);
- Since:
- 1.0
- Version:
- 2022-06-14
-
Constructor Summary
ConstructorsConstructorDescriptionCreate a context without a parent.BeanContext
(BeanContext parentContext) Create a context with a parent. -
Method Summary
Modifier and TypeMethodDescriptionvoid
Adds a bean to the context.void
Adds a bean to the context with a name.void
Connects a bean to the context.void
connectListenersDown
(Object bean) Connects any listener interfaces implemented by the bean to listener lists in this context or any child contexts.void
connectListenersUp
(Object bean) Connects any listener interfaces implemented by the bean to listener lists in this context or any parent contexts.void
destroy()
Destroy the bean context.void
disconnect
(Object bean) Disconnects a bean from the context.<T> T
Returns a bean of the specified type from the context.<T> T
Returns a bean of the specified type from the context.<T> T
Returns a bean with the specified name and type from the context.<T> T
Returns a bean with the specified name and type from the context.<T> List<T>
Returns a set of beans of the specified type from the context.<T> List<T>
Returns a set of beans of the specified type from the context.void
setParent
(BeanContext parent) Set the parent context.void
update()
Updates the context without any phase.void
Updates the context using the specified phase.
-
Constructor Details
-
BeanContext
public BeanContext()Create a context without a parent. -
BeanContext
Create a context with a parent.
-
-
Method Details
-
setParent
Set the parent context. This can only be called if the parent is currently null as it makes no sense to move a context from one parent to another.- Parameters:
parent
- the parent context
-
add
Adds a bean to the context. This can be done at any time, and will simply add the bean to the pending list. In order to trigger autowiring, either update() or update(phase) must be called. This allows any number of beans to be added before wiring occurs.- Parameters:
bean
- the bean to add to the context
-
add
Adds a bean to the context with a name. This can be done at any time and will simply add the bean to the pending list. In order to trigger autowiring, either update() or update(phase) must be called. This allows any number of beans to be added before triggering wiring. The name is optional, however the "qualifier" option of @Autowired references a name which ensures that the correct instance of a bean is returned when there are multiple of the same type available.- Parameters:
name
- the optional unique name of the beanbean
- the bean to add to the context
-
update
public void update()Updates the context without any phase. Once this is called, the context can no longer use phases, as we assume the context is now fully initialized. If any fields are still in the pending list that reference an unused phase, then they will throw an exception, as the assumption is that the phase was accidentally skipped and something is missing. Any non-phase fields that cannot be resolved will also generate an exception.It is still possible to add more beans to the context and call update() again to wire them up. However, as mentioned above, they must all be successful or an exception is thrown.
-
update
Updates the context using the specified phase. This will attempt to resolve only those autowires with the specified phase name and leave all other autowires unprocessed until either update() or update(null) is called. -
destroy
public void destroy()Destroy the bean context. This will release all references to the beans in the context as well as remove any listeners wired from this context to a parent context. -
getBean
Returns a bean with the specified name and type from the context. This will walk up the context hierarchy to find a match.- Type Parameters:
T
- the type of bean to return- Parameters:
name
- the name of the bean to returnclazz
- the class of the bean to return- Returns:
- the requested bean
-
getBean
Returns a bean with the specified name and type from the context. The "inherit" flag can be used to prevent searching parent contexts.- Type Parameters:
T
- the type of bean to return- Parameters:
name
- the name of the bean to returnclazz
- the class of the bean to returninherit
- if true, then search the parent context- Returns:
- the requested bean
-
getBean
Returns a bean of the specified type from the context. If more than one bean is available, the first discovered bean will be returned. This will walk up the context hierarchy to find a match.- Type Parameters:
T
- the type of bean to return- Parameters:
clazz
- the class of the bean to return- Returns:
- the requested bean
-
getBean
Returns a bean of the specified type from the context. If more than one bean is available, the first discovered bean will be returned. The "inherit" flag can be used to prevent searching parent contexts.- Type Parameters:
T
- the type of bean to return- Parameters:
clazz
- the class of the bean to returninherit
- if true, then search the parent context- Returns:
- the requested bean
-
getBeans
Returns a set of beans of the specified type from the context.- Type Parameters:
T
- the type of beans to return- Parameters:
clazz
- the class of the bean to return- Returns:
- the list of requested beans
-
getBeans
Returns a set of beans of the specified type from the context. The "inherit" flag can be used to prevent searching parent contexts.- Type Parameters:
T
- the type of beans to return- Parameters:
clazz
- the class of the bean to returninherit
- if true, then search the parent context- Returns:
- the list of requested beans
-
connect
Connects a bean to the context. This will resolve the autowired fields and attach the bean to any ListenerLists that line up with the interfaces provided by this bean. This does not add the bean to the context, and it will not receive any lifecycle events that context beans receive since this API will either return successful or throw an exception if there's anything that can't be autowired. This is particularly useful for dynamically created beans that want access to some stuff in the context without having to manually look everything up.- Parameters:
bean
- the bean to connect to the context
-
connectListenersUp
Connects any listener interfaces implemented by the bean to listener lists in this context or any parent contexts.- Parameters:
bean
- the bean to connect to the context
-
connectListenersDown
Connects any listener interfaces implemented by the bean to listener lists in this context or any child contexts.- Parameters:
bean
- the bean to connect to the context
-
disconnect
Disconnects a bean from the context. This is only for beans that have been passed toconnect()
and implement a listener interface. A listener is a reverse mapping, from the bean into the context, so it must be explicitly released unless the context the bean is connected is about to destroyed in which case the context will remove the listener reference during the destroy process.- Parameters:
bean
- the bean to disconnect from the context
-