As I have mentioned on different blog entries, I always try to read books, watch videos, take courses and experiment with technologies that I will be using in a project. For example, I have been developing software using the C and C++ programming languages for a long time. That said, I have read a couple dozen books on the subjects. It amazes me that every time I learn something new or question a way I view some concept. In this case I am starting a project using the Spring Framework. The first version was written by Rod Johnson, who released the framework with the publication of his book Expert One-on-One J2EE Design and Development in October 2002. A lot has changed in the past 14 years including new enhancements and tools.
A key concept is to understand what the framework has to offer. One of the key points is the use of Inversion of Control (IoC) and dependency injection. To refresh the subjects I have read a few articles on-line, I am reviewing the book “Dependency Injection in .NET” by Mark Seemann, watching a few videos and experimenting.
On the videos side I got to the following URL: https://srkplanet.wordpress.com/category/spring/ after looking around for a few hours in www.youtube.com.
In software engineering, inversion of control (IoC) is a design principle in which custom-written portions of a computer program receive the flow of control from a generic framework. A software architecture with this design inverts control as compared to traditional procedural programming: in traditional programming, the custom code that expresses the purpose of the program calls into reusable libraries to take care of generic tasks, but with inversion of control, it is the framework that calls into the custom, or task-specific, code. IoC is an object-oriented programming practice whereby the object coupling is bound at run time by an “assembler” object and is typically not knowable at compile time using static analysis.
Inversion of control is used to increase modularity of the program and make it extensible, and has applications in object-oriented programming and other programming paradigms. The term was popularized by Robert C. Martin and Martin Fowler.
The term is related to, but different from, the dependency inversion principle, which concerns itself with decoupling dependencies between high-level and low-level layers through shared abstractions. Spring is an “inversion of control” container for the Java platform.
Shoaib Khan, the author of a series of videos on YouTube and on his Word Press blog, uses an analogy to IoC using a “Servlet Container”. The video series was generated in 2012 and it is somewhat outdated. That said, I strongly recommend any one getting started with Spring to watch the videos and follow along. It is very good for developers that want to learn Spring. If you are familiar or have used versions of Spring, you will be amazed at the nuances you learn by watching and experimenting as you go.
The following code snippets illustrate how IoC may be compared to using a servlet container. I use the STS (Spring Tool Suite) (https://spring.io/) and it seems that the videos are making use of a version of Eclipse (which I also use extensively) when developing Java code.
The story starts with the following code which specifies a base class of Account:
package john.canessa.poly;
public class Account {
public void withdraw() {
}
}
The following derived class for a checking account could be defined:
package john.canessa.poly;
public class CheckingAccount extends Account {
public void withdraw() {
System.out.println(“<<< withdraw in CheckingAccount”);
}
public void overdraft() {
System.out.println(“<<< overdraft in CheckingAccount”);
}
}
The same holds true for a savings account:
package john.canessa.poly;
public class SavingsAccount extends Account {
public void withdraw() {
System.out.println(“<<< withdraw in SavingsAccount”);
}
}
The main differences between the Savings and the Checking account in this example is the operation of the main method withdraw() and the fact that the CheckingAccount class has an additional method overdraft().So far, nothing exciting or atypical happening.
The following main() illustrates the use of the classes in two different ways:
package john.canessa.poly;
import java.util.Scanner;
public class ImplementAccount {
public static void main(String[] args) throws Exception {
Account acc = null;
// **** static (compile time) polymorphism ****
System.out.println(“<<< static polymorhism”);
System.out.println();
acc = new CheckingAccount();
acc.withdraw();
acc = new SavingsAccount();
acc.withdraw();
// **** ****
Scanner sc = new Scanner(System.in);
// **** dynamic polymorphism ****
System.out.println(“<<< dynamic polymorphism”);
System.out.println();
System.out.println(“1\tChecking Account”);
System.out.println(“2\tSavings Account”);
System.out.println();
System.out.print(“>>> account type: “);
int type = sc.nextInt();
// **** create the proper type of account ****
if (type == 1) {
acc = new CheckingAccount();
} else if (type == 2) {
acc = new SavingsAccount();
} else {
throw new Exception(“<<< unexpected account type”);
}
// **** invoke the withdrawal method DYNAMICALLY ****
Decide d = new Decide();
d.invokeMyAccount(acc);
// **** invoke the withdrawal method STATICALLY ****
if (type == 1) {
CheckingAccount c = new CheckingAccount();
c.withdraw();
} else if (type == 2) {
SavingsAccount s = new SavingsAccount();
s.withdraw();
} else {
throw new Exception(“<<< unexpected account type”);
}
// **** close scanner ****
sc.close();
}
}
The first few lines in the main() method illustrates static polymorphism by instantiating and invoking a CheckingAccount and a SavingsAccount objects.
The last few lines in the code illustrate a dynamic approach in which different types of accounts are passed to an instance of the same object Decide. The Decide instance, at run time, should properly handle the differences in the objects passed. This is how a servlet operates and in this case this example illustrates for the Spring IoC container works.
The Decide class follows:
package john.canessa.poly;
public class Decide {
public void invokeMyAccount(Account acc) throws Exception {
// acc.withdraw();
// Class accClass = acc.getClass();
// System.out.println(“<<< accClass: ” + accClass.toString());
// **** Spring IoC (Inversion of Control) container makes the decision for you :o) ****
// if (acc.getClass().equals(CheckingAccount.class)) {
if (acc instanceof CheckingAccount) {
CheckingAccount ca = (CheckingAccount)acc;
ca.withdraw();
ca.overdraft();
// } else if (acc.getClass().equals(SavingsAccount.class)) {
} else if (acc instanceof SavingsAccount) {
SavingsAccount sa = (SavingsAccount)acc;
sa.withdraw();
} else {
throw new Exception(“<<< unexpected account type”);
}
}
}
This static and dynamic treatment of class objects is an important concept in understanding how Spring works.
If you have comments or questions on this blog entry, please send me an email message.
John Canessa
john.canessa@gmail.com