tags:

views:

347

answers:

2

I have created a spring bean that contains a list of other beans, like so:

<bean name="InventoryManager" class="InvManager">
  <property name="slots">
    <bean class="HeadSlot" />
    <bean class="ShoulderSlot" />
    <!-- ... -->
  </property>
</bean>

The problem, though, is that elsewhere I have used an @Autowired annotation in another class to grab a list of all beans implementing a certain interface that some of these inner beans implement, like so:

@Autowired
public void registerInventoryHandlers( List<InvSlot> slots ) {
    //... do some setup stuff with beans that implement the InvSlot interface.
}

The problem here is that apparently the "inner beans" defined in XML are not part of the @Autowired list. However, giving all of these slot beans names and then referencing them from the XML seems unnecessary and ugly.

Is there a way to define a bean inside another bean, but not be an "inner" bean? Or is there a better way to handle this design?

A: 

I have found that using @Component works very nicely.

@Component class InvManager {
    ...
    @Autowired
    public void registerInventoryHandlers( List<InvSlot> slots ) { ... }
}

and

@Component class HeadSlot implements InvSlot { ... }

and

@Component class ShoulderSlot implements InvSlot { ... }

Your configuration becomes

<context:component-scan base-package="com.foo.bar"/>
Paul McKenzie
+2  A: 

Beans defined inside other beans are, by definition, "inner" beans. The docs say:

Inner beans are always anonymous and they are always scoped as prototypes. Please also note that it is not possible to inject inner beans into collaborating beans other than the enclosing bean.

edited to remove stuff that was poorly thought out, irrelevent or just plain wrong

I suggest that rather than autowiring the list of InvSlot beans, you autowire yourself with the InvManager bean instead. You can then ask the InvManager for the list of InvSlot beans, while keeping your list of inner bean definitions inside the InvManager definition.

skaffman
Ah, to the contrary! @Autowired has some surprising, lesser-known uses. To quote Spring's documentation: "It is also possible to provide all beans of a particular type from the ApplicationContext by adding the annotation to a field or method that expects an array of that type"
CaptainAwesomePants
Bloody hell, so it does. I thank you sir, you've taught me a new thing :)
skaffman
I tried to use it to power a sort of "don't need to register yourself" event queue and thought myself bloody clever. But then I ran into this particular can of worms.
CaptainAwesomePants
See edited answer
skaffman