Lazy Singletons

3,690 views
Skip to first unread message

Sam Berlin

unread,
Apr 8, 2009, 1:49:31 PM4/8/09
to google...@googlegroups.com
We use Singletons a lot, and we use Stage.PRODUCTION with singletons to ensure services are created and registered, and listeners are wired together, etc...  While this may not be the "best" use of Singleton, it works really well.  The downside, though, is that it removes the ability to mark something as a non-eager singleton.  Eager construction is a problem when you want super-fast startups (which, well, you always want if you care about startup time).

Creating @LazySingleton is easy enough.  Just a new annotation and a Scope implementation that delegates to Scopes.SINGLETON (it doesn't need to delegate, but it's easier to).  See:
 @LazySingleton: http://tinyurl.com/cbvw5e
 MoreScopes.LAZY_SINGLETON: http://tinyurl.com/d5asxh

It works, but it's kind of frustrating that you still need to inject Provider<Foo> if you want Foo to continue to be lazy.  So, to fix that, I made LazyBinder.  It works on the same principal as AssistedInject -- you bind to a Provider that LazyBinder creates, and internally it creates a Proxy that delegates to the real Provider & gets the underlying object only when a method is called.  LazyBinder ensures that you're creating a proxy only for an @Singleton or @LazySingleton, because otherwise it would make no sense (creating a new object for each method call).

LazyBinder: http://tinyurl.com/ck7k2c

If this is useful to anyone, feel free to use it.  Or, if anyone has suggestions, please offer them.

Sam

limpb...@gmail.com

unread,
Apr 8, 2009, 8:34:27 PM4/8/09
to google-guice
Sam, this is very nice work.

Lack of support for lazy singletons in Stage.PRODUCTION is a Guice
weakness. I'm curious if this is a general problem, or one that only
comes up when singletons are used aggressively for initialization,
like in your app. We don't have them in our apps at Google and so far
there hasn't been much complaining. But we're writing server-side
apps, where eager initialization and slow start-up aren't major
concerns.

I particularly like how you're using aggressive scope checks in
LazyBinder.registerAndCheckTypes(). The compareAndSet() call is also
handy to ensure you only get a single instance. Nice work.

I'm semi-reluctant to include all of this is in core Guice, because I
find that dynamic proxies can cause confusion in debugging I have the
same problem with EasyMock. I'm also anxious about the tradeoffs
between lazy instantiation (great!) and proxying everything (not so
great!).

For now, I've posted a link here from our Scopes wiki:
http://groups.google.com/group/google-guice/browse_thread/thread/e34e475609c2cec4

Cheers,
Jesse

PS - I admit that I'm a horrible hypocrite for giving dynamic proxies
much love in AssistedInject.

limpb...@gmail.com

unread,
Apr 8, 2009, 8:35:58 PM4/8/09
to google-guice
On Apr 8, 5:34 pm, "je...@swank.ca" <limpbiz...@gmail.com> wrote:
> For now, I've posted a link here from our Scopes wiki:
>  http://groups.google.com/group/google-guice/browse_thread/thread/e34e...

Whoops. The Scopes wiki link is
http://code.google.com/p/google-guice/wiki/Scopes

Sam Berlin

unread,
Apr 8, 2009, 9:45:48 PM4/8/09
to google...@googlegroups.com
I agree, LazyBinder is an extension much like AssistedInject and doesn't really belong in core Guice.  Though if AssistedInject were to go in, you'd hear no complaints from me.

Lazy singletons in Stage.PRODUCTION, on the other hand, I think could have a place.  Consider a binding like @Singleton(lazy=true), or bind(Foo.class).in(Scopes.LAZY_SINGLETON) (which would would like Names.named, returning a new @Singleton instance to bind to that had lazy=true set) -- this would be no different than the current Singleton bindings, except with the added feature that the Singleton would be lazily instantiated even if Stage.PRODUCTION was true.

I'm actually not sure right now if Guice could even support something like @Singleton(lazy=true).  Is the ScopingAnnotation passed to the Scope implementation?  That might be something that you want to consider adding.  Even if a lazy singleton isn't your cup of tea, I can imagine there could be other scopes where parameters to the scoping annotation might want to trivially effect the way its scoped.

Sam

Dhanji R. Prasanna

unread,
Apr 8, 2009, 10:05:58 PM4/8/09
to google...@googlegroups.com
I hate dynamic proxies too. =D

Fwiw, I agree with Sam that a strategy for lazy singletons is needed (across the board). Tests can easily exercise on-demand singletons, but declaratively making a singleton lazy in prod is very useful.

This comes up a fair bit internally too, that I think it's worth supporting for Guice 2.

Dhanji.

limpb...@gmail.com

unread,
Apr 9, 2009, 4:14:43 AM4/9/09
to google-guice
On Apr 8, 7:05 pm, "Dhanji R. Prasanna" <dha...@gmail.com> wrote:
> This comes up a fair bit internally too, that I think it's worth supporting
> for Guice 2.

Opened bug 357:
http://code.google.com/p/google-guice/issues/detail?id=357
Reply all
Reply to author
Forward
0 new messages