A crucial difference is the default scope: Spring beans by default are singleton, while Guice beans are prototype. I realized this when a server-communcation service (which at that moment contained session state) started losing connection.
My first approach was annotating the communication service as singleton. But when I tried to inject prototype beans inside such singleton, Guice refused to do it claming that there were a problem with scopes. I was forced to creating a new bean, just to hold the session state.
I though: cool, the framework (Guice ) helped me in order to improve the design. If I were using Spring, the container would have injected such bean (which would be an error, since just the first instantiated prototype woudl be injected).
A few months ago, we started developing a framework for using in Oxen internal projects. It is based on OSGi and Spring DM. I created an agnostic OSGi service which handled the session state data and I wanted to create a custom scope in order to store Spring beans into such session.
Researching a little about custom scopes I found a cool feature, which uses a completely different approach than Guice. The scoped-proxy tag. For example, you can write (importing the appropiate namespaces):
<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"> <aop:scoped-proxy/> </bean>
which creates a proxy for the bean that delegates onto different beans, according to the subjacent scope.
This is pretty cool. For example, yo can inject a bean stored in the HTTP session into a singleton bean and treat the non-singleton bean as it were a singleton. The proxy will be responsible for locating the real bean in the HTTP session.
Both strategies seems good to me. I think that Guice approach imposes some (good) restrictions on the design, while Spring approach gives you more flexibility.