Author: limpbizkit
Date: Fri Sep 19 09:35:09 2008
New Revision: 621
Added:
wiki/Scopes.wiki
Log:
Created wiki page through web user interface.
Added: wiki/Scopes.wiki
==============================================================================
--- (empty file)
+++ wiki/Scopes.wiki Fri Sep 19 09:35:09 2008
@@ -0,0 +1,135 @@
+#summary Overview of writing custom scopes for Guice
+
+= Introduction =
+
+Scopes are one of Guice's most powerful features.
+
+
+= Best Practices =
+
+Prefer to bind with the scope annotation rather than the scope instance:
+{{{
+ // good:
+ bind(Foo.class).in(ServletScopes.REQUEST);
+
+ // better:
+ bind(Bar.class).in(RequestScoped.class);
+}}}
+This way you can reuse the module in a non-servlets environment by
specifying a different scope to implement for `RequestScoped.class`
+
+
+= Custom Scopes =
+
+It is generally recommended that users *do not* write their own custom
scopes -- the built-in scopes should be sufficient for most applications.
If you're writing a web application, the `ServletModule` provides simple,
well tested scope implementations for HTTP requests and HTTP sessions.
+
+In the rare case that you do need a custom scope, `SimpleScope` is a
decent starting point. Copy this class into your project and tweak it to
suit your needs.
+
+{{{
+/**
+ * Scopes a single execution of a block of code. Apply this scope with a
+ * try/finally block: <pre> [EMAIL PROTECTED]
+ *
+ * scope.enter();
+ * try {
+ * // explicitly seed some seed objects...
+ * scope.seed(Key.get(SomeObject.class), someObject);
+ * // create and access scoped objects
+ * } finally {
+ * scope.exit();
+ * }
+ * }</pre>
+ *
+ * The scope can be initialized with one or more seed values by calling
+ * <code>seed(key, value)</code> before the injector will be called upon to
+ * provide for this key. A typical use is for a servlet filter to
enter/exit the
+ * scope, representing a Request Scope, and seed HttpServletRequest and
+ * HttpServletResponse. For each key inserted with seed(), it's good
practice
+ * (since you have to provide <i>some</i> binding anyhow) to include a
+ * corresponding binding that will throw an exception if Guice is asked to
+ * provide for that key if it was not yet seeded: <pre> [EMAIL PROTECTED]
+ *
+ * bind(key)
+ * .toProvider(SimpleScope.<KeyClass>seededKeyProvider())
+ * .in(ScopeAnnotation.class);
+ * }</pre>
+ *
+ * @author Jesse Wilson
+ * @author Fedor Karpelevitch
+ */
+public class SimpleScope implements Scope {
+
+ private static final Provider<Object> SEEDED_KEY_PROVIDER =
+ new Provider<Object>() {
+ @Override
+ public Object get() {
+ throw new IllegalStateException("If you got here then it means
that" +
+ " your code asked for scoped object which should have been" +
+ " explicitly seeded in this scope by calling" +
+ " SimpleScope.seed(), but was not.");
+ }
+ };
+ private final ThreadLocal<Map<Key<?>, Object>> values
+ = new ThreadLocal<Map<Key<?>, Object>>();
+
+ public void enter() {
+ checkState(values.get() == null, "A scoping block is already in
progress");
+ values.set(Maps.<Key<?>, Object>newHashMap());
+ }
+
+ public void exit() {
+ checkState(values.get() != null, "No scoping block in progress");
+ values.remove();
+ }
+
+ public <T> void seed(Key<T> key, T value) {
+ Map<Key<?>, Object> scopedObjects = getScopedObjectMap(key);
+ checkState(!scopedObjects.containsKey(key), "A value for the key %s
was " +
+ "already seeded in this scope. Old value: %s New value: %s", key,
+ scopedObjects.get(key), value);
+ scopedObjects.put(key, value);
+ }
+
+ public <T> void seed(Class<T> clazz, T value) {
+ seed(Key.get(clazz), value);
+ }
+
+ @Override
+ public <T> Provider<T> scope(final Key<T> key, final Provider<T>
unscoped) {
+ return new Provider<T>() {
+ @Override
+ public T get() {
+ Map<Key<?>, Object> scopedObjects = getScopedObjectMap(key);
+
+ @SuppressWarnings("unchecked")
+ T current = (T) scopedObjects.get(key);
+ if (current == null && !scopedObjects.containsKey(key)) {
+ current = unscoped.get();
+ scopedObjects.put(key, current);
+ }
+ return current;
+ }
+ };
+ }
+
+ private <T> Map<Key<?>, Object> getScopedObjectMap(Key<T> key) {
+ Map<Key<?>, Object> scopedObjects = values.get();
+ if (scopedObjects == null) {
+ throw new OutOfScopeException("Cannot access " + key
+ + " outside of a scoping block");
+ }
+ return scopedObjects;
+ }
+
+ /**
+ * Returns a provider that always throws exception complaining that the
object
+ * in question must be seeded before it can be injected.
+ *
+ * @return typed provider
+ */
+ @SuppressWarnings({"unchecked"})
+ public static <T> Provider<T> seededKeyProvider() {
+ return (Provider<T>) SEEDED_KEY_PROVIDER;
+ }
+
+}
+}}}
\ No newline at end of file
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"google-guice-dev" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/google-guice-dev?hl=en
-~----------~----~----~----~------~----~------~--~---