Dependency Injection with Java Spring IoC, A Complete Example


In this post, I’m going to show you how to wire together a simple calculator application using Spring’s Dependency Injection. If you need a refresher on the core concepts, take a look at my earlier article "Understanding Dependency Injection and Its Importance".
The application defines three roles: a Reader that supplies two numbers, an Operation that performs some arithmetic on them, and a Writer that outputs the result. By coding to interfaces, we can swap the concrete implementations (e.g., console vs. file, addition vs. multiplication) without touching the business logic. Spring’s IoC container handles the wiring for us.

Reader Interface:
public interface Reader {
    Operands readValues(String promptMsg);
}

A concrete implementation that reads from the console:
ConsoleReader:
public class ConsoleReader implements Reader{
    Operands oprnds;
    Scanner sc;
    public ConsoleReader (){
        oprnds=new Operands();
        sc=new Scanner(System.in);
    }
    public Operands readValues(String promptMsg) {
        System.out.println(promptMsg);
        oprnds.setOp1(sc.nextLong());
        oprnds.setOp2(sc.nextLong());
        return oprnds;
    }
}


The Operation Interface
public interface Operation {
    Result operate(long op1,long op2);
    String getOperationName();
}

We’ll provide two implementations – multiplication and addition.
Multiply:
public class Multiply implements Operation {
    Result res;
    public Multiply(){
          res=new Result();
    }
    public Result operate(long op1, long op2) {
        res.setRes(op1*op2);
        return res;
    }
    public String getOperationName() {
        return "Multiply";
    }
}

Addition:
public class Add implements Operation {
    Result res;
    public Add(){
        res=new Result();
    }
    public Result operate(long op1, long op2) {
        res.setRes(op1+op2);
        return res;
    }
    public String getOperationName() {
        return "Add";
    }
}


The Writer Interface
public interface Writer {
    void write(Result res);
}

We’ll create a console writer and a text-file writer so you can see how easily the output destination can be changed.
ConsoleWriter:
public class ConsoleWriter implements Writer{
 public void write(Result res){
    System.out.println("The result after operation : "+res.getRes());
  }
}

TXTFileWriter:
public class TXTFileWriter implements Writer{
    File file;
    PrintWriter fwriter;
    public TXTFileWriter(){
        try {
           file = new File("output.txt");
           fwriter = new PrintWriter( new BufferedWriter( new FileWriter(file)));
       } catch (Exception ex) {
           System.err.println(ex);
        }
    }
    public void write(Result res)
  {
     fwriter.println(res.getRes());
     fwriter.close();
    }
}


The Model Classes
The Operands class simply holds two long values with getters and setters. Result wraps a single long value in the same way. I’m showing the essential fields; add getters/setters as needed.
Operands
public class Operands {
    private long op1;
    private long op2;
//setters and getters
}

The Result Class
public class Result {
    private long res;
    //setters and getters
}


Now create a Spring configuration file named confBean.xml in the classpath (e.g., in the src folder). This file tells the IoC container how to instantiate our beans.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<bean id="operation" class="com.gt.spring.operation.Add"/>
<bean id="reader" class="com.gt.spring.reader.ConsoleReader"/>
<bean id="writer" class="com.gt.spring.writer.ConsoleWriter"/>
<beans>

Dependency injection wires these beans together at runtime. In the Main class, we load the context and ask for each bean by its id – no new keyword in sight.
public class Main {
    public static void main(String[] args) {
    ApplicationContext ctx = 
new ClassPathXmlApplicationContext("confBean.xml");
        //get beans from ctx
        Reader rdr = (Reader) ctx.getBean("reader");
        Operation opr = (Operation)ctx.getBean("operation");
        Writer wrt = (Writer) ctx.getBean("writer");//
        //read operands
        Operands opnds = rdr.readValues("Enter the Values :");
        //do operation
        Result res =opr.operate(opnds.getOp1(), opnds.getOp2());
        //write result
        wrt.write(res);
    }
}


No comments :

Post a Comment

Your Comment and Question will help to make this blog better...