views:

678

answers:

3

Hi

** changed the example to better express the situation

i am using spring 2.5 and have the following situation

@Component
@Scope("prototype") 
Class Foo
{
}

class A
{ 
  @Autowired 
  Foo fooA;
}


class B
{ 
  @Autowired 
  Foo fooB;
}



class C
{ 
  @Autowired 
  Foo fooC;
}

i am trying to understand if there is some way to use @Autowired and bind the same instance of FOO onto fooA and fooB while binding a different instance to fooC

i understand that if the scope of FOO will be singleton it will work

but i am wandering if there is a way to achieve the same goal while using a protoype scope.

also please explain is this the correct usage of the autowiring concept ? am i trying to abuse the spring framework purpose

+1  A: 

The whole point of prototype scope is that you get a different instance each time.

Also, autowiring a prototype-scoped bean is questionable, design-wise (in fact, I'd be mildly surprised if it was even permitted). The usual idea is to autowire together beans of the same scope (there are ways around this, but not relevant here).

Everything about your design suggests that Foo should not be a prototype - why have you made it so?

skaffman
the example above is a simplified expression of my situationi am using a bean in the form of prototype because it is needed in my current configuration, there are many places where the bean is injected and a new instance is needed for each of them. but there is a specific place where i would like two objects to share the same instance of the a third object and i wanted to see if it is supproted by spring
Mark
Perhaps you could configure multiple `Foo` singleton beans, and wire them up individually, using `@Autowired @Qualifier`
skaffman
+1  A: 

Autowiring prototype scoped objects is perfectly possible, but a new instance will be created each time. So to answer your question: no, you can't do that.

Your usage of component scanning and autowiring seems ok for the other part.

Christophe Herreman
+3  A: 

Since neither singleton nor prototype scopes seem to fit you (you don't want a single object, but you don't want a new instance each time), you need another scope.

In a web-application context there is a ready solution - use request scope - thus in every request/response cycle you will have only one instance of your bean, no matter where and how many times you inject it.

In a non-web application context you can define your own implementation of org.springframework.beans.factory.config.Scope

Update: after you clarified, this seems like a very strange case. What comes to my mind is the following:

  • define two FactoryBeans (actually - subclasses of AbstractFactoryBean)- one returning new object every time, and one returning the same object (both of them should be in singleton scope)
  • inject the Foos with @Resource(name="prototypeFactoryBean") and @Resource(name="singletonFactoryBean") (instead of @Autowired)
  • the singletonFactoryBean can be designed to just return a singleton (injected in the factory bean class)
  • the prototypeFactoryBean can create a new instance, cast the BeanFactory (available through getBeanFactory()) to AutowireCapableBeanFactory and call .autowire(newlyCreatedBean), and then return it. (alternatively you can inject an ApplicationContext and get its AutowireCapableBeanFactory)

But this is overly complex and you will need extended spring knowledge even after my explanation :)

Furthermore I think you should reconsider your design instead of making the above 'quirks'

Update 2: After your comment, the naming concept is transferred to annotations - as I indicated above you can use @Resource(name="someBean")

Bozho
i am using a non-web configuration, so the suggested solution does not apply, also my explanation above was oversimplified i will revise it
Mark
thanks . i agree with all you said above. i know it seems like a weird scenario but if you think about it there are many occasions in a complex project where several instances of a specific class are shared among other classes. if you think about the spring XML configuration then it is handles very simply by "naming" , you just define two beans with different names represented by the same "code" i was merely trying to see if this capability was transferred to annotations, it seems a little inconsistent
Mark