Class BeanContext

java.lang.Object
com.tccc.kos.commons.core.context.BeanContext

public class BeanContext extends Object
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

    Constructors
    Constructor
    Description
    Create a context without a parent.
    BeanContext(BeanContext parentContext)
    Create a context with a parent.
  • Method Summary

    Modifier and Type
    Method
    Description
    void
    add(Object bean)
    Adds a bean to the context.
    void
    add(String name, Object bean)
    Adds a bean to the context with a name.
    void
    Connects a bean to the context.
    void
    Connects any listener interfaces implemented by the bean to listener lists in this context or any child contexts.
    void
    Connects any listener interfaces implemented by the bean to listener lists in this context or any parent contexts.
    void
    Destroy the bean context.
    void
    Disconnects a bean from the context.
    <T> T
    getBean(Class<? extends T> clazz)
    Returns a bean of the specified type from the context.
    <T> T
    getBean(Class<? extends T> clazz, boolean inherit)
    Returns a bean of the specified type from the context.
    <T> T
    getBean(String name, Class<T> clazz)
    Returns a bean with the specified name and type from the context.
    <T> T
    getBean(String name, Class<T> clazz, boolean inherit)
    Returns a bean with the specified name and type from the context.
    <T> List<T>
    getBeans(Class<T> clazz)
    Returns a set of beans of the specified type from the context.
    <T> List<T>
    getBeans(Class<T> clazz, boolean inherit)
    Returns a set of beans of the specified type from the context.
    void
    Set the parent context.
    void
    Updates the context without any phase.
    void
    update(String phase)
    Updates the context using the specified phase.

    Methods inherited from class java.lang.Object

    equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Constructor Details

    • BeanContext

      public BeanContext()
      Create a context without a parent.
    • BeanContext

      public BeanContext(BeanContext parentContext)
      Create a context with a parent.
  • Method Details

    • setParent

      public void setParent(BeanContext parent)
      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

      public void add(Object bean)
      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

      public void add(String name, Object bean)
      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 bean
      bean - 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

      public void update(String phase)
      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

      public <T> T getBean(String name, Class<T> clazz)
      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 return
      clazz - the class of the bean to return
      Returns:
      the requested bean
    • getBean

      public <T> T getBean(String name, Class<T> clazz, boolean inherit)
      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 return
      clazz - the class of the bean to return
      inherit - if true, then search the parent context
      Returns:
      the requested bean
    • getBean

      public <T> T getBean(Class<? extends T> clazz)
      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

      public <T> T getBean(Class<? extends T> clazz, boolean inherit)
      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 return
      inherit - if true, then search the parent context
      Returns:
      the requested bean
    • getBeans

      public <T> List<T> getBeans(Class<T> clazz)
      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

      public <T> List<T> getBeans(Class<T> clazz, boolean inherit)
      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 return
      inherit - if true, then search the parent context
      Returns:
      the list of requested beans
    • connect

      public void connect(Object bean)
      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

      public void connectListenersUp(Object bean)
      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

      public void connectListenersDown(Object bean)
      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

      public void disconnect(Object bean)
      Disconnects a bean from the context. This is only for beans that have been passed to connect() 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