Class BasicBeanStore

java.lang.Object
org.apache.juneau.commons.inject.BasicBeanStore
All Implemented Interfaces:
AutoCloseable, BeanStore, WritableBeanStore
Direct Known Subclasses:
SpringBeanStore, TestBeanStore

public class BasicBeanStore extends Object implements WritableBeanStore
Basic implementation of WritableBeanStore.

A simple storage database for beans keyed by type and name. Used to retrieve and instantiate beans using an injection-like API. It's similar in concept to the injection framework of Spring but greatly simplified in function and not intended to implement a full-fledged injection framework.

Beans can be stored with or without names. Named beans are typically resolved using the @Name or @Qualified annotations on constructor or method parameters.

This implementation is thread-safe and supports parent bean stores for hierarchical bean resolution.

Resolution order:

Bean lookups consult the following sources in this order, returning the first match:

  1. Overriding parent (e.g. a Spring application context bridge), if non-null.
  2. Local entries added via addBean / addSupplier.
  3. Regular parent, if non-null.
  4. Local default suppliers added via addDefaultSupplier (memoizer-backed framework defaults).
See Also:
  • Field Details

    • INSTANCE

      public static final BasicBeanStore INSTANCE
      Static reusable empty instance.

      Useful as a placeholder when an API requires a BeanStore but the caller has no beans to register — e.g. as the parent argument to a builder that only needs the bean store for downstream parameter resolution.

      Treat this instance as read-only. It's typed as the concrete class so it can be passed to APIs that take WritableBeanStore or BasicBeanStore, but callers should not call any mutating methods on it — doing so would leak state between unrelated callers. Code that legitimately needs to add beans should construct its own new BasicBeanStore().

  • Constructor Details

    • BasicBeanStore

      public BasicBeanStore()
      No-arg constructor. Equivalent to new BasicBeanStore(null).

      Creates a standalone, parent-less bean store. All lookups consult only locally-registered beans and default suppliers.

    • BasicBeanStore

      public BasicBeanStore(BeanStore parent)
      Constructor.
      Parameters:
      parent - The parent bean store. Can be null. Bean searches are performed recursively up this parent chain after local entries are checked.
    • BasicBeanStore

      public BasicBeanStore(BeanStore parent, BeanStore overridingParent)
      Constructor that accepts an overriding parent bean store.

      The overridingParent is consulted before any local entries during bean lookup, allowing an outer scope (typically a Spring ApplicationContext bridge) to take precedence over local registrations. The regular parent continues to be consulted as a fallback after local entries.

      Final resolution order:

      1. overridingParent (if non-null)
      2. local entries (added via addBean / addSupplier)
      3. regular parent (if non-null)
      4. local default suppliers (added via addDefaultSupplier)
      Parameters:
      parent - The parent bean store, used as a fallback after local entries. Can be null (this store then has no parent fallback).
      overridingParent - The overriding parent bean store, consulted before local entries. Can be null (no overriding parent is consulted).
  • Method Details

    • add

      public <T> T add(Class<T> beanType, T bean)
      Same as addBean(Class,Object) but returns the bean instead of this object for fluent calls.
      Specified by:
      add in interface WritableBeanStore
      Type Parameters:
      T - The class to associate this bean with.
      Parameters:
      beanType - The class to associate this bean with. Must not be null.
      bean - The bean. Can be null (stored as an explicit null binding, distinct from no binding at all).
      Returns:
      The bean.
    • add

      public <T> T add(Class<T> beanType, T bean, String name)
      Same as addBean(Class,Object,String) but returns the bean instead of this object for fluent calls.
      Specified by:
      add in interface WritableBeanStore
      Type Parameters:
      T - The class to associate this bean with.
      Parameters:
      beanType - The class to associate this bean with. Must not be null.
      bean - The bean. Can be null (stored as an explicit null binding, distinct from no binding at all).
      name - The bean name if this is a named bean. Can be null for unnamed beans.
      Returns:
      The bean.
    • addBean

      public <T> BasicBeanStore addBean(Class<T> beanType, T bean)
      Adds an unnamed bean of the specified type to this store.
      Specified by:
      addBean in interface WritableBeanStore
      Type Parameters:
      T - The class to associate this bean with.
      Parameters:
      beanType - The class to associate this bean with. Must not be null.
      bean - The bean. Can be null (stored as an explicit null binding, distinct from no binding at all).
      Returns:
      This object.
    • addBean

      public <T> BasicBeanStore addBean(Class<T> beanType, T bean, String name)
      Adds a named bean of the specified type to this store.
      Specified by:
      addBean in interface WritableBeanStore
      Type Parameters:
      T - The class to associate this bean with.
      Parameters:
      beanType - The class to associate this bean with. Must not be null.
      bean - The bean. Can be null (stored as an explicit null binding, distinct from no binding at all).
      name - The bean name if this is a named bean. Can be null for unnamed beans.
      Returns:
      This object.
    • addSupplier

      public <T> BasicBeanStore addSupplier(Class<T> beanType, Supplier<T> bean)
      Adds a supplier for an unnamed bean of the specified type to this store.

      The supplier will be invoked lazily when the bean is first requested.

      Specified by:
      addSupplier in interface WritableBeanStore
      Type Parameters:
      T - The class to associate this bean with.
      Parameters:
      beanType - The class to associate this bean with. Must not be null.
      bean - The bean supplier. Must not be null.
      Returns:
      This object.
    • addSupplier

      public <T> BasicBeanStore addSupplier(Class<T> beanType, Supplier<T> bean, String name)
      Adds a supplier for a named bean of the specified type to this store.

      The supplier will be invoked lazily when the bean is first requested.

      Specified by:
      addSupplier in interface WritableBeanStore
      Type Parameters:
      T - The class to associate this bean with.
      Parameters:
      beanType - The class to associate this bean with. Must not be null.
      bean - The bean supplier. Must not be null.
      name - The bean name if this is a named bean. Can be null for unnamed beans.
      Returns:
      This object.
    • addDefaultSupplier

      public <T> BasicBeanStore addDefaultSupplier(Class<T> beanType, Supplier<T> supplier)
      Adds a fallback supplier for an unnamed bean of the specified type to this store.

      Default suppliers are consulted only after local entries and the regular parent have been searched. They are intended for memoizer-backed framework defaults that should not shadow explicit user registrations or beans inherited from an overriding parent (e.g. Spring).

      Specified by:
      addDefaultSupplier in interface WritableBeanStore
      Type Parameters:
      T - The bean type.
      Parameters:
      beanType - The bean type. Must not be null.
      supplier - The bean supplier. Must not be null.
      Returns:
      This object.
    • addDefaultSupplier

      public <T> BasicBeanStore addDefaultSupplier(Class<T> beanType, Supplier<T> supplier, String name)
      Adds a fallback supplier for a named bean of the specified type to this store.

      See addDefaultSupplier(Class,Supplier) for ordering semantics.

      Specified by:
      addDefaultSupplier in interface WritableBeanStore
      Type Parameters:
      T - The bean type.
      Parameters:
      beanType - The bean type. Must not be null.
      supplier - The bean supplier. Must not be null.
      name - The bean name. Can be null for unnamed beans.
      Returns:
      This object.
    • promoteDefaultsToLocalSuppliers

      Promotes every locally-registered default supplier to a local entry supplier of the same name and type.

      Default suppliers normally resolve at tier 4 (after the regular parent walk), which means a parent store's default supplier wins over this store's default supplier when both are registered for the same type. Promoting moves each default into the tier-2 local-entry slot so that this store's framework defaults take precedence over the parent's same-type defaults — useful for embedded sub-contexts (e.g. per-mixin RestContexts) that need their own framework objects (serializer set, parser set, call logger, etc.) even though the parent is parent-linked for non-framework bean lookups.

      The original default-supplier registrations are left in place; promoted entries that already exist as local entries are not overwritten. Promotion is idempotent and only affects suppliers registered prior to the call — later addDefaultSupplier(...) calls do not retroactively promote.

      Returns:
      This object.
      Since:
      10.0.0
    • pushOverlay

      public Snapshot pushOverlay(BeanStore overlay)
      Description copied from interface: WritableBeanStore
      Pushes the supplied BeanStore onto this store's overlay stack.

      The pushed frame becomes the top-priority lookup target for subsequent bean resolution — it sits above any pre-existing overridingParent setting, this store's local entries, the regular parent chain, and the default-supplier tier. Frames are popped in LIFO order via WritableBeanStore.popOverlay(Snapshot).

      This is the framework primitive behind Mode OVERLAY of the test-injection model: a long-lived SUT's bean store has a per-test overlay pushed at @BeforeEach, then popped at @AfterEach, so subsequent tests see the original beans again with no rebuild cost.

      Composition with overridingParent:

      When this store was constructed with an overriding parent and has overlays pushed on top, the overlay stack wins (it is "more recent"). Both are still consulted before local entries and the regular parent.

      Specified by:
      pushOverlay in interface WritableBeanStore
      Parameters:
      overlay - The bean store to layer on top. Must not be null.
      Returns:
      A Snapshot that must be passed back to WritableBeanStore.popOverlay(Snapshot) to remove the frame.
    • popOverlay

      public void popOverlay(Snapshot snapshot)
      Description copied from interface: WritableBeanStore
      Removes the overlay frame identified by the supplied Snapshot.

      Pops must be issued in LIFO order — the supplied snapshot must identify the current top-of-stack frame. Out-of-order pops, pops on an empty stack, and pops of a snapshot produced by a different store all throw IllegalStateException with a descriptive message. These are programming errors, surfaced loudly rather than silently degraded.

      Specified by:
      popOverlay in interface WritableBeanStore
      Parameters:
      snapshot - The snapshot returned by a prior WritableBeanStore.pushOverlay(BeanStore) call. Must not be null.
    • clear

      Removes all beans from this store.

      This operation only affects this store and does not affect the parent bean store.

      Specified by:
      clear in interface WritableBeanStore
      Returns:
      This object.
    • getBean

      public <T> Optional<T> getBean(Class<T> beanType)
      Returns the unnamed bean of the specified type.

      If no unnamed bean is found in this store, searches the parent store recursively.

      Specified by:
      getBean in interface BeanStore
      Type Parameters:
      T - The type of bean to return.
      Parameters:
      beanType - The type of bean to return. Must not be null.
      Returns:
      The bean, or Optional.empty() if not found.
    • getBean

      public <T> Optional<T> getBean(Class<T> beanType, String name)
      Returns the named bean of the specified type.

      If no bean with the specified name is found in this store, searches the parent store recursively.

      Specified by:
      getBean in interface BeanStore
      Type Parameters:
      T - The type of bean to return.
      Parameters:
      beanType - The type of bean to return. Must not be null.
      name - The bean name. Can be null for unnamed beans.
      Returns:
      The bean, or Optional.empty() if not found.
    • getBeansOfType

      public <T> Map<String,T> getBeansOfType(Class<T> beanType)
      Returns all beans of the specified type, keyed by bean name.

      The map keys are the bean names (empty string for unnamed beans), and the values are the bean instances. Results from the parent store are included first, then beans from this store (which override parent beans with the same name).

      Specified by:
      getBeansOfType in interface BeanStore
      Type Parameters:
      T - The bean type.
      Parameters:
      beanType - The bean type. Must not be null.
      Returns:
      A map of bean names to bean instances. Never null.
    • hasDefaultSupplier

      public boolean hasDefaultSupplier(Class<?> beanType)
      Returns true if this store has a default supplier registered locally for the specified unnamed bean type.

      Parent and overriding-parent stores are not consulted.

      Specified by:
      hasDefaultSupplier in interface WritableBeanStore
      Parameters:
      beanType - The bean type to check. Must not be null.
      Returns:
      true if a default supplier for the unnamed bean type is registered on this store.
    • hasDefaultSupplier

      public boolean hasDefaultSupplier(Class<?> beanType, String name)
      Returns true if this store has a default supplier registered locally for the specified bean type and name.

      Parent and overriding-parent stores are not consulted.

      Specified by:
      hasDefaultSupplier in interface WritableBeanStore
      Parameters:
      beanType - The bean type to check. Must not be null.
      name - The bean name. Can be null for unnamed beans.
      Returns:
      true if a default supplier for the bean type and name is registered on this store.
    • getDefaultSupplier

      public <T> Optional<Supplier<T>> getDefaultSupplier(Class<T> beanType)
      Returns the default supplier registered locally for the specified unnamed bean type, or empty if none.

      Parent and overriding-parent stores are not consulted. This returns the supplier itself, unwrapped from any resolution chain — it lets callers promote a memoizer-backed default supplier into a higher-precedence layer (e.g. a local entry) without re-invoking the underlying factory.

      Type Parameters:
      T - The bean type.
      Parameters:
      beanType - The bean type to look up. Must not be null.
      Returns:
      The locally-registered default supplier, or Optional.empty() if not present.
    • getDefaultSupplier

      public <T> Optional<Supplier<T>> getDefaultSupplier(Class<T> beanType, String name)
      Returns the default supplier registered locally for the specified bean type and name, or empty if none.

      Parent and overriding-parent stores are not consulted. This returns the supplier itself, unwrapped from any resolution chain — it lets callers promote a memoizer-backed default supplier into a higher-precedence layer (e.g. a local entry) without re-invoking the underlying factory.

      Type Parameters:
      T - The bean type.
      Parameters:
      beanType - The bean type to look up. Must not be null.
      name - The bean name. Can be null for unnamed beans.
      Returns:
      The locally-registered default supplier, or Optional.empty() if not present.
    • hasBean

      public boolean hasBean(Class<?> beanType)
      Returns true if this store contains at least one unnamed bean of the specified type.

      If not found in this store, searches the parent store recursively.

      Specified by:
      hasBean in interface BeanStore
      Parameters:
      beanType - The bean type to check. Must not be null.
      Returns:
      true if this store contains at least one unnamed bean of the specified type.
    • hasBean

      public boolean hasBean(Class<?> beanType, String name)
      Returns true if this store contains a bean of the specified type and name.

      If not found in this store, searches the parent store recursively.

      Specified by:
      hasBean in interface BeanStore
      Parameters:
      beanType - The bean type to check. Must not be null.
      name - The bean name. Can be null for unnamed beans.
      Returns:
      true if this store contains a bean of the specified type and name.
    • addBeanType

      public <T> WritableBeanStore addBeanType(Class<T> beanType, Class<? extends T> implType)
      Description copied from interface: WritableBeanStore
      Registers a default implementation class for the specified bean type.

      Type bindings are consulted by callers (notably BeanInstantiator and the various REST memoizers) when resolving the impl class to instantiate for beanType. This is the type-binding analogue of addDefaultSupplier: it provides a deferred-construction default that can be overridden by later resolution steps (e.g. an annotation override).

      Specified by:
      addBeanType in interface WritableBeanStore
      Type Parameters:
      T - The bean type.
      Parameters:
      beanType - The bean type to bind.
      implType - The implementation class to instantiate when this type is resolved.
      Returns:
      This object for method chaining.
    • getBeanType

      public <T> Optional<Class<? extends T>> getBeanType(Class<T> beanType)
      Description copied from interface: BeanStore
      Returns the implementation class registered for the specified bean type, if any.

      Type bindings let callers register a default implementation class to be instantiated when an actual bean of beanType is needed. Bindings are inherited through the parent chain.

      The default implementation returns Optional.empty() (no binding). Override in concrete stores (see BasicBeanStore) to enable type binding.

      Specified by:
      getBeanType in interface BeanStore
      Type Parameters:
      T - The bean type.
      Parameters:
      beanType - The bean type whose implementation class is being looked up.
      Returns:
      The implementation class, or Optional.empty() if no binding exists.
    • getBeanSupplier

      public <T> Optional<Supplier<T>> getBeanSupplier(Class<T> beanType)
      Returns the supplier for an unnamed bean of the specified type.

      If no supplier is found in this store, searches the parent store recursively.

      Specified by:
      getBeanSupplier in interface BeanStore
      Type Parameters:
      T - The bean type.
      Parameters:
      beanType - The bean type. Must not be null.
      Returns:
      The supplier, or Optional.empty() if no supplier of the specified type exists.
    • resolve

      protected <T> Optional<Supplier<T>> resolve(Class<T> beanType, String name)
      Resolves a supplier for a bean of the specified type and name.

      If no supplier with the specified name is found in this store, searches the parent store recursively.

      Type Parameters:
      T - The bean type.
      Parameters:
      beanType - The bean type. Must not be null.
      name - The bean name. Can be null for unnamed beans.
      Returns:
      The supplier, or Optional.empty() if no supplier of the specified type and name exists.
    • getBeanSupplier

      public <T> Optional<Supplier<T>> getBeanSupplier(Class<T> beanType, String name)
      Returns the supplier for a named bean of the specified type.

      If no supplier with the specified name is found in this store, searches the parent store recursively.

      Specified by:
      getBeanSupplier in interface BeanStore
      Type Parameters:
      T - The bean type.
      Parameters:
      beanType - The bean type. Must not be null.
      name - The bean name. Can be null for unnamed beans.
      Returns:
      The supplier, or Optional.empty() if no supplier of the specified type and name exists.
    • registerConfiguration

      Description copied from interface: WritableBeanStore
      Registers a configuration class and its Bean-annotated members.
      Specified by:
      registerConfiguration in interface WritableBeanStore
      Parameters:
      configType - The configuration type.
      Returns:
      This object.
    • createBeanFromMethod

      public <T> Optional<T> createBeanFromMethod(Class<T> beanType, Object onClassOrObject, Predicate<MethodInfo> filter, Object... extraBeans)
      Finds and invokes a factory method that produces a bean of type beanType.

      If onClassOrObject is a Class, only static methods are eligible. Otherwise, both instance and static methods on the object's class are eligible. A null filter accepts any qualifying method.

      The search has two passes. The first pass considers public methods only (unchanged behavior). If it finds nothing, the second pass considers non-public methods across the class hierarchy, child class first, but only those carrying @Bean (declared directly or inherited from a method they override; see BeanAnnotation.find(MethodInfo)). Bridge/synthetic methods, interface static methods and deprecated methods are skipped, as are parent methods overridden by an already-seen child method. A non-public method without @Bean is never invoked, even when filter is null. Non-public methods are made accessible before invocation.

      Example:

      public class MyResource { @Bean RichLogger logger() { return new RichLogger(); } // Package-private, found by the second pass. } Optional<RichLogger> logger = beanStore.createBeanFromMethod(RichLogger.class, new MyResource());

      Specified by:
      createBeanFromMethod in interface BeanStore
      Type Parameters:
      T - The bean type.
      Parameters:
      beanType - The type of bean to create. Must not be null.
      onClassOrObject - The object instance or Class whose methods are searched. Must not be null.
      filter - Optional predicate restricting which methods are eligible. Can be null (any method qualifies).
      extraBeans - Optional bean instances visible to parameter resolution for this call only.
      Returns:
      The created bean wrapped in an Optional, or Optional.empty() if no matching factory method was found.
      Throws:
      BeanCreationException - If a matching method was found but threw an exception during invocation.
      See Also:
    • toString

      public String toString()
      Overrides:
      toString in class Object
    • properties

    • close

      public void close() throws BeanCreationException
      Description copied from interface: WritableBeanStore
      Closes this bean store, invoking pre-destroy callbacks.
      Specified by:
      close in interface AutoCloseable
      Specified by:
      close in interface WritableBeanStore
      Throws:
      BeanCreationException - on shutdown failures.