Women in Technology

Hear us Roar



Article:
  Twelve Best Practices For Spring XML Configurations
Subject:   i beg to differ
Date:   2006-01-28 00:35:26
From:   trollswagen
I disagree with your recommendation for autowiring. If you are explicitly setting constructor or property injection, you end up coupling your components, and by a static name!


I think it is a good discipline to have all of your dependencies against interfaces and use autowire="byType", which searches the ApplicationContext for any beans that implement the interfaces you depend on. If you want to add a dependency to a class, all you would need to do is specify a new setter in your class, and forget about changing the context file. If you want to require that all dependencies are set, you can use the dependency-check attribute on the bean. Another alternative is to specify, in the init-method attribute, a method to validate and throw IllegalArgumentExceptions.


For naming conventions I like to use the interface that the class is implementing, for example:
<bean id="org.phiz.bam.PowerTool" class="org.phiz.bam.tools.Drill" autowire="byType" dependency-check="objects"/>
This has an added benefit, if your IDE will allow you to access the interface or the class from the context file itself... IDEA does by pressing Ctrl and left-clicking the name of the class or interface.


Also, I found it very useful to have context files with only one bean in them, such as:
tool_PowerDrill.xml -> specifies PowerDrill bean which implements PowerTool
tool_PowerScrewDriver.xml -> specifies ScrewDriver bean which implements PowerTool and ScrewDriver
worker_Carpenter.xml -> specifies Carpenter bean with dependency on ScrewDriver
worker_Electrician.xml -> specifies Electrician bean with dependency on PowerTool


Then you can build a large variety of components just by combining different context files, such as:
ApplicationContext appCtx = new ClassPathXmlApplicationContext("worker_Carpenter.xml", "tool_PowerDrill.xml");
ApplicationContext appCtx = new ClassPathXmlApplicationContext("worker_Carpenter.xml", "tool_PowerScrewDriver.xml");
ApplicationContext appCtx = new ClassPathXmlApplicationContext("worker_Electrician.xml", "tool_PowerDrill.xml");
ApplicationContext appCtx = new ClassPathXmlApplicationContext("worker_Electrician.xml", "tool_PowerScrewDriver.xml");
or even
ApplicationContext appCtx = new ClassPathXmlApplicationContext("worker_Carpenter.xml", "worker_Electrician.xml", "tool_PowerScrewDriver.xml");
so now they can share the same PowerTool instance, or have their own instances of the tool (using the singleton="false" attribute on the bean).


The real weakness in autowiring is that if spring finds more than one bean in the ApplicationContext to satisfy a dependency, it will throw an exception. So you have to find another way of wiring array or list dependencies. You can solve this problem by explicitly setting the property in the context file, or programatically (see below).


I definitely prefer property to constructor injection. As you may have noticed, not a lot (if any) spring framework classes have constructor arguments.


Another thing that I highly recommend is creating an abstraction layer for the ApplicationContext. Sometimes you need to have awareness of beans in the ApplicationContext without creating a direct dependency on spring. This is particularly useful if you wish to plug multiple implementations of an interface into a class.


An abstraction layer can also help you create a "private" ApplicationContext's within a class (i.e., to spawn worker threads, or for a prototype factory), and to create child contexts. For instance:
<bean id="org.phiz.bam.Worker"
class="org.phiz.bam.workers.Carpenter" autowire="byType">
<description>I have a dependency on Toolbox</description>
</bean>


<bean id="org.phiz.bam.ToolBox"
class="org.phiz.bam.boxes.CarpenterToolBox">
<property name="containerContext">
<bean class="org.phiz.ioc.SpringContainerContext">
<property name="internalLayer">
<list>
<value>tool_PowerDrill.xml</value>
<value>tool_ScrewDriver.xml</value>
<value>tool_Hammer.xml</value>
<value>${context.file.for.nail.prototype}</value>
</list>
</property>
</bean>
</property>
</bean>


Finally, the spring framework LOVES TO BE ABUSED! Use it every day, as often as you can, for all your applications!!!


It is up to good designers and architects to make the right decisions in terms of how to structure and load the context files. That is how you avoid the VERY REAL pitfalls of readability and maintainability.

Main Topics Oldest First

Showing messages 1 through 1 of 1.

  • location of better edit of this comment
    2006-01-28 01:47:00  trollswagen [View]

    http://iocaopossrule.blogspot.com/2006/01/dissenting-opinion.html