001/***************************************************************************** 002 * Copyright (c) PicoContainer Organization. All rights reserved. * 003 * ------------------------------------------------------------------------- * 004 * The software in this package is published under the terms of the BSD * 005 * style license a copy of which has been included with this distribution in * 006 * the LICENSE.txt file. * 007 * * 008 * Idea by Rachel Davies, Original code by various * 009 *****************************************************************************/ 010package org.picocontainer; 011 012import org.picocontainer.lifecycle.LifecycleState; 013 014import java.util.Properties; 015 016/** 017 * This is the core interface used for registration of components with a container. It is possible to register 018 * implementations and instances here 019 * 020 * @author Paul Hammant 021 * @author Aslak Hellesøy 022 * @author Jon Tirsén 023 * @see <a href="package-summary.html#package_description">See package description for basic overview how to use PicoContainer.</a> 024 */ 025public interface MutablePicoContainer extends PicoContainer, Startable, Disposable { 026 027 /** 028 * Register a component and creates specific instructions on which constructor to use, along with 029 * which components and/or constants to provide as constructor arguments. These "directives" are 030 * provided through an array of <tt>Parameter</tt> objects. Parameter[0] correspondes to the first constructor 031 * argument, Parameter[N] corresponds to the N+1th constructor argument. 032 * <h4>Tips for Parameter usage</h4> 033 * <ul> 034 * <li><strong>Partial Autowiring: </strong>If you have two constructor args to match and you only wish to specify one of the constructors and 035 * let PicoContainer wire the other one, you can use as parameters: 036 * <code><strong>new ComponentParameter()</strong>, new ComponentParameter("someService")</code> 037 * The default constructor for the component parameter indicates auto-wiring should take place for 038 * that parameter. 039 * </li> 040 * <li><strong>Force No-Arg constructor usage:</strong> If you wish to force a component to be constructed with 041 * the no-arg constructor, use a zero length Parameter array. Ex: <code>new Parameter[0]</code> 042 * <ul> 043 * 044 * @param componentKey a key that identifies the component. Must be unique within the container. The type 045 * of the key object has no semantic significance unless explicitly specified in the 046 * documentation of the implementing container. 047 * @param componentImplementationOrInstance 048 * the component's implementation class. This must be a concrete class (ie, a 049 * class that can be instantiated). Or an intance of the compoent. 050 * @param parameters the parameters that gives the container hints about what arguments to pass 051 * to the constructor when it is instantiated. Container implementations may ignore 052 * one or more of these hints. 053 * 054 * @return the same instance of MutablePicoContainer 055 * 056 * @throws PicoCompositionException if registration of the component fails. 057 * @see org.picocontainer.Parameter 058 * @see org.picocontainer.parameters.ConstantParameter 059 * @see org.picocontainer.parameters.ComponentParameter 060 */ 061 MutablePicoContainer addComponent(Object componentKey, 062 Object componentImplementationOrInstance, 063 Parameter... parameters); 064 065 /** 066 * Register an arbitrary object. The class of the object will be used as a key. Calling this method is equivalent to 067 * calling <code>addComponent(componentImplementation, componentImplementation)</code>. 068 * 069 * @param implOrInstance Component implementation or instance 070 * 071 * @return the same instance of MutablePicoContainer 072 * 073 * @throws PicoCompositionException if registration fails. 074 */ 075 MutablePicoContainer addComponent(Object implOrInstance); 076 077 /** 078 * Register a config item. 079 * 080 * @param name the name of the config item 081 * @param val the value of the config item 082 * 083 * @return the same instance of MutablePicoContainer 084 * 085 * @throws PicoCompositionException if registration fails. 086 */ 087 MutablePicoContainer addConfig(String name, Object val); 088 089 /** 090 * Register a component via a ComponentAdapter. Use this if you need fine grained control over what 091 * ComponentAdapter to use for a specific component. The adapter will be wrapped in whatever behaviors that the 092 * the container has been set up with. If you want to bypass that behavior for the adapter you are adding, 093 * you should use Characteristics.NONE like so pico.as(Characteristics.NONE).addAdapter(...) 094 * 095 * @param componentAdapter the adapter 096 * 097 * @return the same instance of MutablePicoContainer 098 * 099 * @throws PicoCompositionException if registration fails. 100 */ 101 MutablePicoContainer addAdapter(ComponentAdapter<?> componentAdapter); 102 103 /** 104 * Unregister a component by key. 105 * 106 * @param componentKey key of the component to unregister. 107 * 108 * @return the ComponentAdapter that was associated with this component. 109 */ 110 <T> ComponentAdapter<T> removeComponent(Object componentKey); 111 112 /** 113 * Unregister a component by instance. 114 * 115 * @param componentInstance the component instance to unregister. 116 * 117 * @return the same instance of MutablePicoContainer 118 */ 119 <T> ComponentAdapter<T> removeComponentByInstance(T componentInstance); 120 121 /** 122 * Make a child container, using both the same implementation of MutablePicoContainer as the parent 123 * and identical behaviors as well. 124 * It will have a reference to this as parent. This will list the resulting MPC as a child. 125 * Lifecycle events will be cascaded from parent to child 126 * as a consequence of this. 127 * <p>Note that for long-lived parent containers, you need to unregister child containers 128 * made with this call before disposing or you will leak memory. <em>(Experience 129 * speaking here! )</em></p> 130 * <p>Incorrect Example:</p> 131 * <pre> 132 * MutablePicoContainer parent = new PicoBuilder().withCaching().withLifecycle().build(); 133 * MutablePicoContainer child = parent.makeChildContainer(); 134 * child = null; //Child still retains in memory because parent still holds reference. 135 * </pre> 136 * <p>Correct Example:</p> 137 * <pre> 138 * MutablePicoContainer parent = new PicoBuilder().withCaching().withLifecycle().build(); 139 * MutablePicoContainer child = parent.makeChildContainer(); 140 * parent.removeChildContainer(child); //Remove the bi-directional references. 141 * child = null; 142 * </pre> 143 * @return the new child container. 144 */ 145 MutablePicoContainer makeChildContainer(); 146 147 /** 148 * Add a child container. This action will list the the 'child' as exactly that in the parents scope. 149 * It will not change the child's view of a parent. That is determined by the constructor arguments of the child 150 * itself. Lifecycle events will be cascaded from parent to child 151 * as a consequence of calling this method. 152 * 153 * @param child the child container 154 * 155 * @return the same instance of MutablePicoContainer 156 * 157 */ 158 MutablePicoContainer addChildContainer(PicoContainer child); 159 160 /** 161 * Remove a child container from this container. It will not change the child's view of a parent. 162 * Lifecycle event will no longer be cascaded from the parent to the child. 163 * 164 * @param child the child container 165 * 166 * @return <code>true</code> if the child container has been removed. 167 * 168 */ 169 boolean removeChildContainer(PicoContainer child); 170 171 172 /** 173 * You can change the characteristic of registration of all subsequent components in this container. 174 * 175 * @param properties 176 * @return the same Pico instance with changed properties 177 */ 178 MutablePicoContainer change(Properties... properties); 179 180 /** 181 * You can set for the following operation only the characteristic of registration of a component on the fly. 182 * 183 * @param properties 184 * @return the same Pico instance with temporary properties 185 */ 186 MutablePicoContainer as(Properties... properties); 187 188 /** 189 * Name the container instance, to assist debugging or other indexing. 190 * 191 * @param name the name to call it. 192 * @since 2.8 193 */ 194 void setName(String name); 195 196 /** 197 * To assist ThreadLocal usage, LifecycleState can be set. No need to use this for normal usages. 198 * @param lifecycleState the lifecyle state to use. 199 * @since 2.8 200 */ 201 void setLifecycleState(LifecycleState lifecycleState); 202 203 204 /** 205 * Retrieve the name set (if any). 206 * @return Retrieve the arbitrary name of the container set by calling {@link #setName(String) setName}. 207 * @since 2.10.2 208 */ 209 String getName(); 210 211 212 /** 213 * Allow querying of the current lifecycle state of a MutablePicoContainer. 214 * @return the current Lifecycle State. 215 * @since 2.10.2 216 */ 217 LifecycleState getLifecycleState(); 218}