Dependency injection introduction
Let’s first review the concept of dependency injection:
Dependency Injection and Inversion of Control, which we often mention are the same concept. The specific meaning is: when a role (maybe a Java instance, caller) needs the assistance of another role (another Java instance, caller), in the traditional programming process, the caller is usually created by the caller. But in Spring, the work of creating the callee is no longer done by the caller, so it is called control inversion; the work of creating the callee instance is usually done by the Spring container and then injected into the caller, so it is also called dependency injection.
In fact, simply put, the role of dependency injection is to decouple the dependencies between objects from the original code, and to add Spring framework processing to allow us to flexibly and centrally manage dependencies.
Dependency injection framework
Dependency injection framework is not mysterious, it is actually a very simple thing. Don't look at the spring's dependency injection source code, because as long as you go, it means that you will never write again and you will not dare to start by yourself. Its function is too powerful, so the design is too complicated. Ordinary programmers can only sigh at the sight of it.
I didn't read the spring source code carefully. Even so, it only took half a day to apply a small framework iockids that basically meets the standard dependency injection standard "JSR-330". This small framework has only one main class Injector, with about 200 lines of code, and it has the following functions.
Let's look at a slightly more complicated example of usage
import javax.inject.Inject;import javax.inject.Named;import javax.inject.Singleton;import iockids.Injector;@Singletonclass Root { @Inject @Named("a") Node a; @Inject @Named("b") Node b; @Override public String toString() { return String.format("root(%s, %s)", a.name(), b.name()); }}interface Node { String name();}@Singleton@Named("a")class NodeA implements Node { @Inject Leaf leaf; @Inject @Named("b") Node b; @Override public String name() { if (b == null) return String.format("nodeA(%s)", leaf); else return String.format("nodeAWithB(%s)", leaf); }}@Singleton@Named("b")class NodeB implements Node { Leaf leaf; @Inject @Named("a") Node a; @Inject public NodeB(Leaf leaf) { this.leaf = leaf; } @Override public String name() { if (a == null) return String.format("nodeB(%s)", leaf); else return String.format("nodeBWithA(%s)", leaf); }}class Leaf { @Inject Root root; int index; static int sequence; public Leaf() { index = sequence++; } public String toString() { if (root == null) return "leaf" + index; else return "leafwithroot" + index; }}public class Demo { public static void main(String[] args) { var injector = new Injector(); injector.registerQualifiedClass(Node.class, NodeA.class); injector.registerQualifiedClass(Node.class, NodeB.class); var root = injector.getInstance(Root.class); System.out.println(root); }}The above code uses all the functions provided by iockids.
To facilitate understanding of the above code, I drew a dependency diagram
The above code output is as follows
root(nodeAWithB(leafwithroot0), nodeBWithA(leafwithroot1))
From this output, we can also roughly imagine the dependency structure.
iockids provides rich injection error exception reports to prevent user injection configuration errors.
For example, if we configure the names of NodeA and NodeB above to the same a, the error stack below will be exposed.
iockids.InjectException: duplicated qualified javax.inject.Named with the same class iockids.demo.Node at iockids.Injector.registerQualifiedClass(Injector.java:87) at iockids.Injector.registerQualifiedClass(Injector.java:70) at iockids.demo.Demo.main(Demo.java:106)
If we add a parameter to the constructor of NodeB at will
@Inject public NodeB(Leaf leaf, int k) { this.leaf = leaf; }The following error will be thrown when running
iockids.InjectException: no accessible constructor for injection class int at iockids.Injector.createNew(Injector.java:120) at iockids.Injector.createNew(Injector.java:94) at iockids.Injector.createFromParameter(Injector.java:167) at iockids.Injector.createFromConstructor(Injector.java:145) at iockids.Injector.createNew(Injector.java:123) at iockids.Injector.createFromQualified(Injector.java:216) at iockids.Injector.createFromField(Injector.java:173) at iockids.Injector.injectMembers(Injector.java:233) at iockids.Injector.createNew(Injector.java:136) at iockids.Injector.createFromQualified(Injector.java:216) at iockids.Injector.createFromField(Injector.java:173) at iockids.Injector.injectMembers(Injector.java:233) at iockids.Injector.createNew(Injector.java:136) at iockids.Injector.createNew(Injector.java:94) at iockids.Injector.getInstance(Injector.java:245) at iockids.demo.Demo.main(Demo.java:107)
Project open source address: https://github.com/pyloque/iockids (local download)
Summarize
The above is the entire content of this article. I hope that the content of this article has certain reference value for everyone's study or work. If you have any questions, you can leave a message to communicate. Thank you for your support to Wulin.com.