001package io.dinject;
002
003import java.io.Closeable;
004import java.util.List;
005
006/**
007 * Holds beans created by dependency injection.
008 * <p>
009 * The beans have singleton scope, support lifecycle methods for postConstruct and
010 * preDestroy and are created (wired) via dependency injection.
011 * </p>
012 *
013 * <h3>Create a BeanContext</h3>
014 * <p>
015 * We can programmatically create a BeanContext via BeanContextBuilder.
016 * </p>
017 * <pre>{@code
018 *
019 *   // create a BeanContext ...
020 *
021 *   try (BeanContext context = new BeanContextBuilder()
022 *     .build()) {
023 *
024 *     CoffeeMaker coffeeMaker = context.getBean(CoffeeMaker.class);
025 *     coffeeMaker.makeIt()
026 *   }
027 *
028 * }</pre>
029 *
030 * <h3>Implicitly used</h3>
031 * <p>
032 * The BeanContext is implicitly used by SystemContext.  It will be created as needed and
033 * a shutdown hook will close the underlying BeanContext on JVM shutdown.
034 * </p>
035 * <pre>{@code
036 *
037 *   // BeanContext created as needed under the hood
038 *
039 *   CoffeeMaker coffeeMaker = SystemContext.getBean(CoffeeMaker.class);
040 *   coffeeMaker.brew();
041 *
042 * }</pre>
043 */
044public interface BeanContext extends Closeable {
045
046  /**
047   * Return the module name of the bean context.
048   *
049   * @see ContextModule
050   */
051  String getName();
052
053  /**
054   * Return the names of module features this bean context provides.
055   *
056   * @see ContextModule
057   */
058  String[] getProvides();
059
060  /**
061   * Return the names of modules this bean context depends on.
062   *
063   * @see ContextModule
064   */
065  String[] getDependsOn();
066
067  /**
068   * Return a single bean given the type.
069   *
070   * <pre>{@code
071   *
072   *   CoffeeMaker coffeeMaker = beanContext.getBean(CoffeeMaker.class);
073   *   coffeeMaker.brew();
074   *
075   * }</pre>
076   *
077   * @param type an interface or bean type
078   */
079  <T> T getBean(Class<T> type);
080
081  /**
082   * Return a single bean given the type and name.
083   *
084   * <pre>{@code
085   *
086   *   Heater heater = beanContext.getBean(Heater.class, "electric");
087   *   heater.heat();
088   *
089   * }</pre>
090   *
091   * @param type an interface or bean type
092   * @param name the name qualifier of a specific bean
093   */
094  <T> T getBean(Class<T> type, String name);
095
096  /**
097   * Return the wiring candidate bean with name and priority.
098   */
099  <T> BeanEntry<T> candidate(Class<T> type, String name);
100
101  /**
102   * Return the list of beans that have an annotation.
103   *
104   * <pre>{@code
105   *
106   *   // e.g. register all controllers with web a framework
107   *   // .. where Controller is an annotation on the beans
108   *
109   *   List<Object> controllers = SystemContext.getBeansWithAnnotation(Controller.class);
110   *
111   * }</pre>
112   *
113   * <p>
114   * The classic use case for this is registering controllers or routes to
115   * web frameworks like Sparkjava, Javlin, Rapidoid etc.
116   *
117   * @param annotation An annotation class.
118   */
119  List<Object> getBeansWithAnnotation(Class<?> annotation);
120
121  /**
122   * Return the list of beans that implement the interface.
123   *
124   * <pre>{@code
125   *
126   *   // e.g. register all routes for a web framework
127   *
128   *   List<WebRoute> routes = SystemContext.getBeans(WebRoute.class);
129   *
130   * }</pre>
131   *
132   * @param interfaceType An interface class.
133   */
134  <T> List<T> getBeans(Class<T> interfaceType);
135
136  /**
137   * Return the list of beans that implement the interface
138   * sorting by priority (ignoring any Priority annotation).
139   */
140  <T> List<T> getBeansByPriority(Class<T> interfaceType);
141
142  /**
143   * Sort the beans by javax.annotation.Priority annotation.
144   *
145   * @param list The beans to sort by priority
146   * @return A new list of beans sorted by priority
147   */
148  <T> List<T> sortByPriority(List<T> list);
149
150  /**
151   * Start the context firing any <code>@PostConstruct</code> methods.
152   */
153  void start();
154
155  /**
156   * Close the context firing any <code>@PreDestroy</code> methods.
157   */
158  void close();
159}