1 /*
2 * Copyright 2006-2016 The JGUIraffe Team.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License")
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package net.sf.jguiraffe.di;
17
18 import java.util.Set;
19
20 /**
21 * <p>
22 * Definition of an interface for objects that provide access to beans.
23 * </p>
24 * <p>
25 * A <em>bean</em> is a plain old Java object that is somehow defined (e.g. its
26 * concrete class, some initialization properties, or some methods to be
27 * invoked). When the <code>BeanProvider</code> is asked for the bean it is
28 * responsible for, it has to ensure that it has been created and completely
29 * initialized. Then it can be handed over to the calling instance. It is up to
30 * a concrete implementation how this is achieved. One implementation can for
31 * instance always return the same bean instance, effectively implementing the
32 * <em>singleton</em> pattern. Another implementation could create a new bean
33 * instance on each request, which would be appropriate for a stateful service
34 * bean.
35 * </p>
36 * <p>
37 * The most interesting part of a bean provider is the fact that it can depend
38 * on other bean providers (which in turn can have dependencies on further
39 * providers and so on). These dependencies are dynamically resolved when a bean
40 * is requested, which can lead to a whole bunch of objects being created and
41 * initialized. The resulting bean is then fully initialized and ready for
42 * service. (These are the well-known concepts of <em>dependency injection</em>
43 * and <em>inversion of control (IoC)</em>.
44 * </p>
45 * <p>
46 * The most important method of a <code>BeanProvider</code> is the
47 * <code>getBean()</code> method, which returns the fully initialized bean
48 * maintained by this provider. For the proper initialization of the bean and
49 * dynamic resolving of dependencies the <code>getDependencies()</code> method
50 * is also of importance.
51 * </p>
52 * <p>
53 * While providing a reference to the managed bean is naturally the main task of
54 * a bean provider, there are some other methods defined in this interface.
55 * These methods have a more technical background; they allow the dependency
56 * injection framework to effectively manage access to bean stores, especially
57 * if they are concurrently used by multiple threads. To better understand these
58 * methods some words about synchronization and threading issues are necessary:
59 * </p>
60 * <p>
61 * An access to the bean provided by a <code>BeanProvider</code> is
62 * automatically synchronized by the framework. This means that until the bean
63 * is completely created and initialized, no other thread can access this
64 * provider. If there are cyclic references in the dependency graph however
65 * (e.g. bean A depends on bean B, which depends on bean C, which again depends
66 * on bean A), the <code>getBean()</code> method can be entered again by the
67 * same thread. An implementation should be aware of this. The invocation of a
68 * bean provider's <code>getBean()</code> method is also called a
69 * <em>transaction</em>. If the bean store is concurrently accessed by other
70 * threads, it has to be ensured that the whole initialization process of a bean
71 * is not disturbed by other threads. The framework takes care about this. With
72 * the additional methods defined by this interface a <code>BeanProvider</code>
73 * implementation can obtain information about the start and the end of such
74 * transactions.
75 * </p>
76 * <p>
77 * When an application is about to shut down or when a {@code BeanStore} is
78 * closed, it is often necessary to do some clean up. For beans created by the
79 * framework - especially singleton service beans - it may be required to invoke
80 * a specific shutdown method, for instance if the bean is a database connection
81 * pool or something like that. For this purpose the {@code BeanProvider}
82 * interface defines the {@code shutdown()} method. Here a concrete
83 * implementation can place code for cleaning up the beans created by it.
84 * </p>
85 *
86 * @author Oliver Heger
87 * @version $Id: BeanProvider.java 205 2012-01-29 18:29:57Z oheger $
88 */
89 public interface BeanProvider
90 {
91 /**
92 * <p>
93 * Returns the bean managed by this provider. This is the main method of a
94 * <code>BeanProvider</code>. A concrete implementation can do whatever
95 * is necessary to obtain the requested bean. Depending on the provider's
96 * semantic it can decide whether the bean is cached after it has been
97 * created, or whether for each request a new bean has to be created.
98 * </p>
99 * <p>
100 * The passed in reference to a <code>DependencyProvider</code> can be
101 * used for obtaining needed dependencies. This method will be automatically
102 * synchronized by the framework. However if there are cyclic dependencies,
103 * querying the <code>DependencyProvider</code> may cause the method to be
104 * entered again. An implementation must be aware of this to avoid endless
105 * loops.
106 * </p>
107 * <p>
108 * If a problem occurs when creating and initializing the bean, an
109 * implementation should throw a <code>{@link InjectionException}</code>
110 * exception.
111 * </p>
112 *
113 * @param dependencyProvider the dependency provider
114 * @return the bean managed by this provider
115 */
116 Object getBean(DependencyProvider dependencyProvider);
117
118 /**
119 * Returns the class of the bean managed by this provider. Clients may query
120 * beans based on their class. So it becomes necessary to ask a provider for
121 * the bean class without having to create the bean first. A
122 * <code>DependencyProvider</code> is passed in that can be used for
123 * resolving the class (in case only the class name is known to the
124 * provider)
125 *
126 * @param dependencyProvider the dependency provider, which can be used for
127 * resolving the bean class
128 * @return the class of the bean managed by this provider
129 */
130 Class<?> getBeanClass(DependencyProvider dependencyProvider);
131
132 /**
133 * Returns a set with the descriptions of the beans this provider depends
134 * on. These are typically beans the managed bean is to be initialized with
135 * through dependency injection. This method is called once by the framework
136 * whenever a transaction starts (i.e. when client code queries either this
137 * bean or a bean that depends on this provider). Its return value need not
138 * be constant over time (for instance a provider that always returns the
139 * same bean does not need any dependencies any more after the bean has been
140 * initialized on first access).
141 *
142 * @return a set with the dependency descriptions of the beans this bean
143 * provider depends on (can be <b>null</b> if there are no dependencies)
144 * @see Dependency
145 */
146 Set<Dependency> getDependencies();
147
148 /**
149 * Returns the ID of the transaction that locked this bean provider. A
150 * transaction locks each <code>BeanProvider</code> it depends on, so that
151 * it cannot be concurrently accessed by another thread. This is done using
152 * the <code>setLockID()</code>. An implementation will typically store
153 * the value passed in here and return it in <code>getLockID()</code>.
154 * However if a concrete implementation does not need any synchronization
155 * (e.g. because it only returns a constant object), it can always return
156 * <b>null</b> here.
157 *
158 * @return the ID of the locking transaction or <b>null</b> if there is
159 * none
160 */
161 Long getLockID();
162
163 /**
164 * Locks or unlocks this <code>BeanProvider</code>. This method is called
165 * with the ID of the current transaction to mark this provider as blocked.
166 * After that it cannot be accessed by a different thread until the locking
167 * transaction ends. Before it ends it will call this method again with a
168 * value of <b>null</b>. This method, in conjunction with the
169 * <code>getLockID()</code> method, is related to the implementation of
170 * synchronized access to bean providers. A <code>BeanProvider</code>
171 * implementation that requires synchronization should store the value
172 * passed in here in a member field and return it in the
173 * <code>getLockID()</code> method. An implementation that is thread-safe
174 * can leave this method empty and return always <b>null</b> in
175 * <code>getLockID()</code>.
176 *
177 * @param lid the ID of the locking transaction
178 * @see #getLockID()
179 */
180 void setLockID(Long lid);
181
182 /**
183 * Checks whether the bean managed by this provider can now be retrieved.
184 * This method can be used for detecting cyclic references: A bean may need
185 * other beans as arguments for its creation (e.g. for calling its
186 * constructor). This may cause the creation of these dependent beans. If
187 * one of these depends on the original bean, there is a cyclic dependency.
188 * Complex bean providers supporting enhanced bean creation and
189 * initialization should implement this method to return <b>false</b> if
190 * their managed bean is currently in the creation phase and thus does not
191 * really exist yet. A caller may then decide to try again later when the
192 * creation is complete. Simple bean providers can always return <b>true</b>.
193 *
194 * @return a flag whether the managed bean is available
195 */
196 boolean isBeanAvailable();
197
198 /**
199 * Notifies this {@code BeanProvider} that it (and the bean(s) created by
200 * it) is no longer needed. A concrete implementation can use this method to
201 * perform some cleanup. It is also an opportunity for invoking a shutdown
202 * method on the bean created by this provider. Typically this method will
203 * be called when the {@code BeanStore} this {@code BeanProvider} belongs to
204 * is closed.
205 *
206 * @param dependencyProvider the {@code DependencyProvider}
207 */
208 void shutdown(DependencyProvider dependencyProvider);
209 }