The Case for Spring Inner Beans
When code reviewing or pair programming, I’m always amazed by the following discrepancy. On one hand, 99% of developers conscientiously apply encapsulation and limit accessibility and variable scope to the minimum possible. On the other hand, nobody cares one bit about Spring beans and such beans are always set at top-level, which makes them accessible from every place where you can get a handle on the Spring context.
For example, this a typical Spring beans configuration file:
<bean id="one" class="ch.frankel.blog.spring.One" />
<bean id="two" class="ch.frankel.blog.spring.Two" />
<bean id="three" class="ch.frankel.blog.spring.Three" />
<property name="one" ref="one" />
<property name="two" ref="two" />
</bean>
<bean id="four" class="ch.frankel.blog.spring.Four" />
<bean id="five" class="ch.frankel.blog.spring.Five">
<property name="three" ref="three" />
<property name="four" ref="four" />
</bean>If beans one, two, three and four are only used by bean five, they shouldn’t be accessible from anywhere else and should be defined as inner beans.
<bean id="five">
<property name="three">
<bean class="ch.frankel.blog.spring.Three">
<property name="one">
<bean class="ch.frankel.blog.spring.One" />
</property>
<property name="two">
<bean class="ch.frankel.blog.spring.Two" />
</property>
</bean>
</property>
<property name="four">
<bean class="ch.frankel.blog.spring.Four" />
</property>
</bean>From this point on, beans one, two, three and four cannot be accessed in any way outside of bean five; in effect, they are not visible.
There are a couple of points I’d like to make:
- By using inner beans, those beans are implicitly made anonymous but also scoped
prototype, which doesn’t mean squat since they won’t be reused anywhere else. - With annotations configuration, this is something that is done under the cover when you set a new instance in the body of the method
- I acknowledge it renders the Spring beans definition file harder to read but with the graphical representation feature brought by Spring IDE, this point is moot
In conclusion, I would like every developer to consider not only technologies, but also concepts. When you understand variable scoping in programming, you should not only apply it to code, but also wherever it is relevant.
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)






Comments
Dan Holmes replied on Mon, 2013/02/11 - 12:21pm
I'm not sure I agree that prototype scope doesn't mean anything for inner beans. With default prototype scope, if you create 10 instances of bean five, you'll get 10 instances each of beans one, two, three, and four. If those inner beans were set to singleton scope, you'd get 10 instances of five, but a single shared instance of one, two, three, and four.
Am I missing something?
Nicolas Frankel replied on Mon, 2013/02/11 - 12:33pm
in response to:
Dan Holmes
Well, it's how it's described in the documentation. You're welcome to unit-test their assertions, I would really be interested in the results.
Dan Holmes replied on Tue, 2013/02/12 - 12:37pm
I ran some tests. The documentation is correct - the inner beans appear to always be prototype scope. However, your conclusion that "this doesn't mean squat" is incorrect. Forced prototype scope means a lot. If you instantiate bean five multiple times, you will get multiple, distinct instances of beans one, two, three, and four. If you want singleton behavior (a single instance of bean one for several instances of bean five), I think you are out of luck. Developers should understand this limitation very carefully. If a given design requires singleton behavior, this will mean that inner beans should be avoided.
Nicolas Frankel replied on Tue, 2013/02/19 - 4:20am
in response to:
Dan Holmes
Following my article, Oliver Gierke created this Jira. It seems the two of you disagree...
Dan Holmes replied on Tue, 2013/02/19 - 11:11am
Actually, I think he confirmed my point. If I'm reading the ticket correctly (which is difficult - there's not much detail there), he also demonstrated that multiple instances of the inner beans are created. He's disputing whether they should have destruction callbacks applied, which has nothing to do with the original article or any of my comments. I'm not even sure he's correct when he says that prototypes shouldn't be affected by lifecycle methods, but it's unrelated to the point I was trying to make, so I won't worry about it.
Nicolas, are you of the opinion that there will only ever be a single instance of each defined inner bean, no matter how many instances of the "outer" bean are created? If so, that's not prototype scope, that's singleton scope. Or, are you of the opinion that multiple instances of the inner beans can be created? If so, that's prototype scope, but then it's wrong to say it "doesn't mean squat". It means a lot, and if you need to restrict the bean to a single instance in the container, you apparently can't do it with an inner bean definition.
I'm not trying to be a jerk. I just think there's possibly a bit of misinformation in your article, and I'd hate to see someone misled and subsequently introduce some unexpected behavior into their code.