Print
Injection Methods Compared

The injection methods supported by a ioc container is a primary aspect of expressiveness of the container.

Pico, Spring, Nuts all support primitive injection methods such as constructor injection, setter injection, factory method injection.

Either through out-of-box ComponentAdapter, or a custom ComponentAdapter implementation, it is always possible for Pico to implement anything we talk about here, though some may require substantial coding. This comparison is primarily between Spring and Nuts since both provide an XML syntax.

Constructor Injection

Spring:

<bean id="acct" class="BankAccount">
  <constructor-arg index="0"><value>100</value></constructor-arg>
</bean>

Nuts:

<ctor id="acct" class="BankAccount" args="100"/>

Setter Injection

Spring:

<bean id="acct" class="BankAccount">
  <property name="balance"><value>100</value></property>
</bean>

Nuts:

<bean id="acct" class="BankAccount" props="{balance=100}"/>

Static Factory Method Injection

Spring:

<bean id="acct" class="BankAccount" factory-method="getInstance">
  <constructor-arg index="0"><value>100</value></constructor-arg>
</bean>

Nuts:

<method id="acct" class="BankAccount" name="getInstance" args="100"/>

Instance Factory Method Injection

Spring:

<bean id="myFactoryBean" .../>
<bean id="acct" factory-bean="myFactoryBean" factory-method="getInstance">
  <constructor-arg index="0"><value>100</value></constructor-arg>
</bean>

Nuts:

<bean id="myFactoryBean" .../>
<bean id="acct" component="$myFactoryBean" name="getInstance" args="100"/>

Referencing Field

Spring:

<bean id="myField"
    class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean">
  <property name="staticField"><value>java.lang.System.out</value></property>
</bean>

Nuts:

<field id="myField" class="java.lang.System" name="out"/>

Call a static factory and then call an instance method

This example is copied from Spring reference manual. Spring calls this "a bit verbose". It is used to read a system property.

Java:

String javaVersion(){
  Properties sysProps = System.getProperties();
  return sysProps.getProperty("java.version");
}

Spring:

<bean id="sysProps" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
  <property name="targetClass"><value>java.lang.System</value></property>
  <property name="targetMethod"><value>getProperties</value></property>
</bean>

<bean id="javaVersion" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
  <property name="targetObject"><ref local="sysProps"/></property>
  <property name="targetMethod"><value>getProperty</value></property>
  <property name="arguments">
    <list>
      <value>java.version</value>
    </list>
  </property>
</bean>

Nuts:

<sequence id="javaVersion">
  <method var="sysProps" class="java.lang.System" name="getProperties" args=""/>
  <method component="$sysProps" name="getProperty" args="java.version"/> 
</sequence>

Ad-hoc logic

This example may not be very realistic. It is just created to demonstrate the expressiveness of Nuts.

Java:

BankAccount getAccount(){
  Logger package_logger = logfactory.getLoggerForPackage("com.ajoo");
  Logger stdout = logfactory.getLogger(System.out);
  Logger logger = new SequenceLogger(package_logger, stdout);
  logger.setLogLevel(Logger.WARNING);
  BankAccountFactory factory = new BankAccountFactoryImpl(logger, 1000);
  Bank bank = new Bank(logger);
  BankAccount acct = factory.createBankAccount(logger);
  acct.setBank(bank);
}

Spring: Well. I'm not gonna try to do it in Spring to save time. Write it out yourself if you are patient enough to do it in Spring.

Nuts:

<sequence id="getAccount">
  <method var="package_logger" component="$logfactory"
    name="getLoggerForPackage" args="com.ajoo"/>
  <method var="stdout" component="$logfactory" name="getLogger">
    <args>
      <field class="java.lang.System" name="out"/>
    </args>
  </method>
  <ctor var="logger" class="SequenceLogger" args="$package_logger, $stdout"/>
  <setter component="$logger" name="logLevel">
    <field class="Logger" name="WARNING"/>
  </setter>
  <ctor var="factory" class="BankAccountFactoryImpl" args="$logger, 1000"/>
  <ctor var="bank" class="Bank" args="$logger"/>
  <method var="acct" component="$factory" name="createBankAccount" args="$logger"/>
  <bean var="result" component="$acct" props="{bank=$bank}"/>
</sequence>

As you can see, the Nuts xml reads pretty much consistent with the Java code. The "var" attribute is used as local variable to save the result of each statement. The names prefixed with '$' refer to variables.

Indeed, Nuts support almost everything you can do in a full blown programming language. As an extreme case, you can even do the "call-with-current-continuation" using the <callcc> tag.

Powered by Atlassian Confluence