Simply About Spring

This article focuses on the popular Spring framework. It’s an essential topic for Java beginners, as Spring is a widely used technology.

First, let’s consider wiring — the dynamic assembly of separate beans, the most important part of the Spring Framework. It’s important to keep in mind that a good understanding of fundamental concepts is an irreplaceable skill for any great programmer.

Spring framework works with module-based applications, so let’s take a brief look at a simple program which performs arithmetic operations.

public class CalcExample {

    public CalcExample() {
    } 

    public static void main(String[] args) {
        CalcExample calc = new CalcExample(); calc.execute(args);
    } 

    private void printResult(String result) {
        System.out.println(result);
    } 

    private long operate(long number1, long number2) {
        return number1 + number2;
    }

    private String getOpsName() {
        return " plus ";
    }

    public void execute(String [] args) {
        long number1 = Long.parseLong(argument[0]);
        long number2 = Long.parseLong(argument[1]);
        printResult("The result of " + number1 + getOpsName() + number2 +
        " is " + operate(number1, number2) + "!");
    }
}

Nice code for beginners, but we have to obtain a program that contains several modules, which can be changed in a simple way. It’s a very useful method of software development – separating code into parts you can change, couple of them, or add following to rules, complying with the rules described in interfaces (or just implement it).

So we need an interface in our program, let’s do it:

public interface Operation {
    long operate(long op1, long op2);
    String getOpsName();
}

Addition

public class OpAdd implements Operation {
    public OpAdd() {
    }

    public String getOpsName() {
        return " plus "; 
    }

    public long operate(long number1, long number2) {
        return number1 + number2; 
    } 
}

Mutiply

public class OpMultiply implements Operation {
    public OpMultiply() {
    }

    public String getOpsName() {
        return " times ";
    }

    public long operate(long number1, long number2) {
        return number1 * number2;
    }
}

public class CalcExampleBeans {
    private Operation ops = new OpAdd();
    private ResultWriter wtr = new ScreenWriter();

    public static void main(String[] args) {
        CalcExampleBeans calc = new CalcExampleBeans();
        calc.execute(args);
    }

    public void execute(String [] args) {
        long number1 = Long.parseLong(argument[0]);
        long number2 = Long.parseLong(argument[1]);
        wtr.showResult("The result of " + number1 + ops.getOpsName() + number2 + 
        " is " + ops.operate(number1, number2) + "!");
    }
}

Well, we have two separate beans, OpAdd and OpMultiply, which both implement the interface Operation. Everything is clean, but what will we do if we need to change a bean during program execution?

Here, Spring can help us. By dynamically connecting beans via the build.xml file, Spring creates a container for assembling components with their dependencies.

The beauty of this solution is that CalculateSpring does not work with instances of Operation or ResultWriter, but delegates this task to the Spring container. Spring container, in turn, reads the configuration XML file and calls the bean descriptor.

import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class CalculateSpring {
    private Operation ops; private ResultWriter wtr;

    public void setOps(Operation ops) {
        this.ops = ops;
    }

    public void setWriter(ResultWriter writer) {
        this.wtr = writer;
    } 

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        BeanFactory factory = (BeanFactory) context;
        CalculateSpring calc =(CalculateSpring) factory.getBean("opsbean");
        calc.execute(args);
    }

    public void execute(String [] args) {
        long number1 = Long.parseLong(argument[0]);
        long number2 = Long.parseLong(argument[1]);
        wtr.showResult("The result of " + number1 + ops.getOpsName() + number2 + " is " + ops.operate(number1, number2) + "!");
    }
}

So we create a context, factory, and via the factory, we can get beans. ApplicationContext in Spring is a type of BeanFactory. BeanFactory provides access to initialized JavaBeans that are connected to and managed by the Spring container. Although there are other BeanFactory classes in Spring, ApplicationContext is much more commonly used because it provides several valuable features, including support for internationalization, resource loading, integration with external hierarchy contexts, and more.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans"
 xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="https://www.springframework.org/schema/beans
 https://www.springframework.org/schema/beans/spring-beans-2.0.xsd">

  <bean id="screen" class="com.wrox.begspring.ScreenWriter" />

  <bean id="multiply" class="com.wrox.begspring.OpMultiply" />

  <bean id="add" class="com.wrox.begspring.OpAdd" />

  <bean id="opsbean" class="com.wrox.begspring.CalculateSpring">
    <property name="ops" ref="multiply" /> <property name="writer" ref="screen"/>
  </bean>

</beans> 

The article will continue next week, when we’ll talk about Inversion of Control (IoC) in Spring.

Software Developer