ColdSpring Constructor Arguments
Many ColdFusion developers have standardized on a method named init() that acts as a constructor for the component. ColdSpring will automatically call the constructor for any components that it manages. In cases where the constructor requires arguments to be passed into it, you can specify constructor arguments in your ColdSpring XML file, like this:
<bean id="configBean" class="coldspring.examples.quickstart.components.ConfigBean"> <constructor-arg name="datasourceName"> <value>myDSN</value> </constructor-arg> </bean>
This will ensure that when ColdSpring creates the ConfigBean and calls its constructor, it will pass in an argument named "datasourceName" with a value of "myDSN" to the init() method. For reference, the init() method for our ConfigBean CFC looks similar to:
<cffunction name="init" access="public" returntype="any" hint="Constructor."> <cfargument name="datasourceName" type="string" /> <cfset variables.instance['datasourceName'] = arguments.datasourceName /> <cfreturn this /> </cffunction>
In addition to defining simple values, you can also specify other ColdSpring-managed components as constructor arguments:
<bean id="userGateway" class="coldspring.examples.quickstart.components.UserGateway"> <constructor-arg name="configBean"> <ref bean="configBean" /> </constructor-arg> </bean>
With this code, when ColdSpring calls the constructor on the UserGateway, it will pass in an argument named "configBean", and its value will be the actual ConfigBean instance that ColdSpring is also managing. For reference, a constructor that requires passing a component as a constructor argument might look like:
<cffunction name="init" access="public" returntype="any" hint="Constructor."> <cfargument name="configBean" type="any" /> <cfset variables.instance['configBean'] = arguments.configBean /> <cfreturn this /> </cffunction>
When Should I Use Constructor Arguments vs. Setter Injection?
You may have noticed that there are essentially two ways to feed data into the CFCs that ColdSpring is managing. One is through constructor arguments, and the other is by calling setter methods like we saw in the ColdSpring in 5 Minutes example. So which way should you do it?
For CFC data that are simple values, using a constructor argument to set the value is often fine. However, when passing dependent CFCs into a component, setter injection is often preferable. This has to do with the idea of circular dependencies.
A circular dependency can happen when two CFC's actually depend on each other. i.e., ComponentA depends on ComponentB, but ComponentB depends on ComponentA! Now what do we do? When using constructor arguments we can be in a bit of trouble. But using setter injection means that ColdSpring can create the two components and then use setter methods to inject them into each other. This way we don't run into a deadlock where neither component can be created because they both need each other to have their constructors called.
If that doesn't make much sense, don't worry. Just remember that as a general rule, using setter injection is often more flexible than using constructor arguments to inject dependent components.