Spring Inversion of Control (IOC)

Contents

Introduction
Installing
Usage
Example
XML Configuration Details

Introduction

Inversion of control is a technique that allows object configuration to be moved out of code and into a configuration file. With Spring IOC, this is typically done with an XML file. Some of the key features of Spring IOC are setter injection, constructor injection and auto-wiring. These are demonstrated in the example below.

Javadoc for all of the Spring Framework can be found here.

Installing top

Spring can be downloaded from here. To use it from Java applications, insure that spring.jar, found in the dist subdirectory, is in the classpath.

Usage top

The basic steps to use Spring IOC are:

  1. Write Java Bean classes, with get and set methods for each property to be configured by Spring. These can optionally implement interfaces.
  2. Create an XML file the describes the Java Beans to be configured. Beans can also be described using a Java property file, but using XML is more common.
  3. Use an XMLBeanFactory to create configured beans. There are other ways to read bean descriptions, but using an XmlBeanFactory is more common.

Here is the basic layout of a Spring XML configuration file.

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean ...>...</bean>+ </beans>

XMLBeanFactory validates the XML, so the DOCTYPE is required.

To use an XMLBeanFactory, write code similar to this.

import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.xml.XmlBeanFactory; import org.springframework.core.io.FileSystemResource; ... BeanFactory beanFactory = new XmlBeanFactory(new FileSystemResource("spring-beans.xml")); // Also consider using ClassPathResource. MyBeanInterface bean = (MyBeanInterface) beanFactory.getBean("myBeanId");

To read the XML file from the WAR of a web app., use ClassPathResource instead of FileSystemResource. To read the XML file from a URL, use UrlResource. See the javadoc for org.springframework.core.io.Resource for more options.

Example top

This example demonstrates the following.

Here is the XML configuration file, spring-beans.xml. Note how the property names match the get/set methods in the associated bean classes.

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <!-- This demonstrates setter injection. --> <bean id="config1" class="com.ociweb.springdemo.Config"> <!-- can specify value with a child element --> <property name="color"> <value>yellow</value> </property> <!-- can specify value with an attribute --> <property name="number" value="19"/> </bean> <!-- This demonstrates constructor injection. --> <bean id="config2" class="com.ociweb.springdemo.Config"> <constructor-arg value="yellow"/> <constructor-arg value="19"/> </bean> <!-- This demonstrates setter injection of another bean. --> <bean id="myService1" class="com.ociweb.springdemo.MyServiceImpl"> <property name="config" ref="config1"/> </bean> <!-- This bean doesn't need an id because it will be associated with another bean via autowire by type. --> <bean class="com.ociweb.springdemo.Car"> <property name="make" value="Honda"/> <property name="model" value="Prelude"/> <property name="year" value="1997"/> <property name="color" value="black"/> </bean> <!-- This demonstrates auto-wiring by type. --> <!-- Valid values for the autowire attribute are no, byName, byType, constructor, autodetect and default. --> <bean id="insurance1" class="com.ociweb.springdemo.InsuranceImpl" autowire="byType"> <!-- If Insurance had properties that couldn't be set by type, child elements such as the following would be needed. --> <!--property name="otherProperty" value="otherValue"/--> </bean> </beans>

Here is the Config class. Note how the get/set methods for color and number match the property names in the "config1" bean in the XML configuration file. Also, note how the Config class has a constructor that accepts the constructor-arg values in the "config2" bean in the XML configuration file.

package com.ociweb.springdemo; public class Config { private String color; private int number; public Config() {} public Config(String color, int number) { this.color = color; this.number = number; } public void setColor(String color) { this.color = color; } public String getColor() { return color; } public void setNumber(int number) { this.number = number; } public int getNumber() { return number; } public String toString() { return "Config: color=" + color + ", number=" + number; } }

Here is the MyService interface. Note how the getConfig/setConfig methods match the config property of the "myService1" bean in the XML configuration file. The Config bean that will be passed to the setConfig method is the one with an id of "config1".

package com.ociweb.springdemo; public interface MyService { public void setConfig(Config config); public Config getConfig(); public void doSomething(); }

Here is the MyServiceImpl class. It implements the MyService interface.

package com.ociweb.springdemo; public class MyServiceImpl implements MyService { private Config config; public Config getConfig() { return config; } public void setConfig(Config config) { this.config = config; } public void doSomething() { System.out.println("config = " + config); } }

Here is the Car class. Note how the get/set methods for color, make, model and year match the property names in the Car bean in the XML configuration file.

package com.ociweb.springdemo; public class Car { private String color; private String make; private String model; private int year; public String getColor() { return color; } public String getMake() { return make; } public String getModel() { return model; } public int getYear() { return year; } public void setColor(String color) { this.color = color; } public void setMake(String make) { this.make = make; } public void setModel(String model) { this.model = model; } public void setYear(int year) { this.year = year; } public String toString() { return year + " " + make + " " + model + " in " + color; } }

Here is the Insurance interface. Note how the getCar/setCar methods do not match any property name in the insurance1 bean in the XML configuration file. This is because auto-wiring is being used. There must be only one configured bean that is a com.ociweb.springdemo.Car object. Since this interface has get/set methods for that type of object, it will be configured with that one Car bean.

package com.ociweb.springdemo; public interface Insurance { public void setCar(Car car); public Car getCar(); public void getQuote(); }

Here is the InsuranceImpl class. It implements the Insurance interface.

package com.ociweb.springdemo; public class InsuranceImpl implements Insurance { private Car car; public Car getCar() { return car; } public void setCar(Car car) { this.car = car; } public void getQuote() { System.out.println("quote for " + car + " is ?"); } }

Here is the class that obtains and uses beans that are created and configured using Spring IOC.

package com.ociweb.springdemo; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.xml.XmlBeanFactory; import org.springframework.core.io.FileSystemResource; public class Demo { public static void main(String[] args) { BeanFactory beanFactory = new XmlBeanFactory(new FileSystemResource("spring-beans.xml")); // Get a bean configured from primitive values. Config config = (Config) beanFactory.getBean("config1"); System.out.println("config = " + config); // Get a bean configured from another bean. MyService myService = (MyService) beanFactory.getBean("myService1"); myService.doSomething(); // Get a bean configured through auto-wire by type. Insurance insurance = (Insurance) beanFactory.getBean("insurance1"); System.out.println("insurance is for " + insurance.getCar()); } }

XML Configuration Details top

For details on the syntax of the XML configuration files, see spring-beans-2.0.dtd.

The allowed attributes of the beans element are

The allowed child elements of the beans element are

The allowed attributes of the bean element are

The allowed child elements of the bean element are

The constructor-arg element, a child of bean elements, is used in constructor injection.

The allowed attributes of the constructor-arg element are

Note that index and type are only needed to avoid< selecting the wrong overloaded constructor.

The allowed child elements of the constructor-arg element are

The meta element, a child of bean elements, is used to attach arbitrary metadata to beans. It has key and value attributes. It is not used by Spring, but could be used by custom code that parses this XML.


Copyright © 2007 Object Computing, Inc. All rights reserved.