What is Control Inversion and Dependency Injection
The full English name of Inversion of Control is IoC. It makes it possible to form a loosely coupled structure between program components and classes. Developers need to create instances of objects before using instances of classes. But IoC entrusts the task of creating instances to the IoC container, so that only instances of classes need to be used directly when developing application code. This is IoC control inversion. Usually we use a so-called Hollywood principle ("Don't call me. I will call you." Please don't call me, I'll call you.) This is a metaphor for the relationship of inversion of control. Martin Fowler devoted an article to the concept of inversion of control and proposed a more accurate concept called Dependency Injection (DI).
[Example] A printer simulator is developed using Spring dependency injection.
Example requirements:
(1) Can flexibly configure the use of color cartridges or gray cartridges.
(2) It is flexible to configure the cost of printing pages.
The results of implementation are as follows:
Program structure diagram:
(1) Define Ink cartridge interface and IPaper paper interface.
package y2ssh.pjb.di.ink; /** * Ink cartridge interface * @author pan_junbiao **/ public interface Ink { public String getColor(int r,int g, int b); }
package y2ssh.pjb.di.paper; /** * Paper interface * @author pan_junbiao **/ public interface IPaper { public static final String newline = "\r\n"; /** * Output a character to paper */ public void putInChar(char c); /** * Get the output to paper */ public String getContent(); }
(2) Printer class is developed using Ink interface and IPaper interface.
package y2ssh.pjb.di; import y2ssh.pjb.di.ink.Ink; import y2ssh.pjb.di.paper.IPaper; /** * Printer program * @author pan_junbiao **/ public class Printer { private Ink ink = null; private IPaper paper = null; public void print(String str) { //Output color marker System.out.println("Use"+ink.getColor(255,200,0)+"Color Printing:"); //Character-by-character output to paper for(int i=0; i<str.length(); i++) { paper.putInChar(str.charAt(i)); } //Output of Paper Content System.out.println(paper.getContent()); } public void setInk(Ink ink) { this.ink = ink; } public void setPaper(IPaper paper) { this.paper = paper; } }
The Printer class has only one print() method. The input parameter is a string to be printed. The printer enters the string character by character into the paper and then outputs the contents of the paper.
When developing Printer class programs, we only need to understand Ink interface and IPaper interface, which are completely independent of the implementation of these interfaces.
We also need to provide "slots" so that the use of assembly can "inject" instance objects of Ink and IPaper interfaces, which are setter methods, setInk() methods and setPaper() methods in Java code.
(3) Develop the implementation classes of Ink interface and IPaper interface: ColorInk, GreyInk and TextPaper.
package y2ssh.pjb.di.ink; import java.awt.Color; /** * Color cartridge * @author pan_junbiao **/ public class ColorInk implements Ink { public String getColor(int r,int g, int b) { Color color = new Color(r,g,b); return "#" + Integer.toHexString(color.getRGB()).substring(2); } }
package y2ssh.pjb.di.ink; import java.awt.Color; /** * Grey ink cartridge * @author pan_junbiao **/ public class GreyInk implements Ink { public String getColor(int r,int g, int b) { int c = (r+g+b)/3; Color color = new Color(c,c,c); return "#" + Integer.toHexString(color.getRGB()).substring(2); } }
package y2ssh.pjb.di.paper; /** * Realization of Text Printing Paper * @author pan_junbiao **/ public class TextPaper implements IPaper { private String content = ""; //Paper content private int charPerLine = 16; //Number of characters per line private int linePerPage = 5; //Number of rows per page private int posX = 0; //Current horizontal position, from 0 to charPerLine-1 private int posY = 0; //Current row number, linePerPage-1 private int posP = 1; //Current page number //Setter method for attribute injection public void setCharPerLine(int charPerLine) { this.charPerLine = charPerLine; } public void setLinePerPage(int linePerPage) { this.linePerPage = linePerPage; } public void putInChar(char c) { content += c; ++posX; //Judging whether to change lines if (posX == charPerLine) { content += IPaper.newline; posX = 0; ++posY; } //Judging whether to turn the page if (posY == linePerPage) { content += "== The first" + posP + "page =="; content += IPaper.newline + IPaper.newline; posY = 0; ++ posP; } } public String getContent() { return this.content; } }
(4) Assembly Printer (Spring Dependency Injection)
Add Spring's jar package and commons-logging.jar file to the project.
Create the application Context. XML configuration file in the src directory.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <!-- Spring configuration file --> <beans> <bean id="colorInk" class="y2ssh.pjb.di.ink.ColorInk"/> <bean id="greyInk" class="y2ssh.pjb.di.ink.GreyInk"/> <bean id="a4Paper" class="y2ssh.pjb.di.paper.TextPaper"> <property name="charPerLine" value="160"/> <property name="linePerPage" value="8"/> </bean> <bean id="b5Paper" class="y2ssh.pjb.di.paper.TextPaper"> <property name="charPerLine" value="90"/> <property name="linePerPage" value="5"/> </bean> <!-- Assemble a color, use B5 Printer for Printing Paper --> <bean id="printer_color_b5" class="y2ssh.pjb.di.Printer"> <property name="ink" ref="colorInk"/> <property name="paper" ref="b5Paper"/> </bean> <!-- Assemble a gray one for use A4 Printer for Printing Paper --> <bean id="printer_grey_a4" class="y2ssh.pjb.di.Printer"> <property name="ink" ref="greyInk"/> <property name="paper" ref="a4Paper"/> </bean> </beans>
(5) Running test
package y2ssh.pjb.di; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * Operation test * @author pan_junbiao **/ public class DITest { public static void main(String[] args) { //Loading configuration files ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); //Get a printer instance (a color printer using B5 printing paper) Printer colorPrinter = (Printer)context.getBean("printer_color_b5"); String str = "Hello, welcome to visit pan_junbiao Blogs!\n" + "Blog address: https://blog.csdn.net/pan_junbiao\n" + "Time has never been quiet, but someone is carrying yoke for you, moving forward with tears. Maybe it's a parent, a friend or a stranger. Whoever you are, please remember to be always grateful."; colorPrinter.print(str); } }