Today, I would like to introduce a detailed explanation of the principle of SpringIoc. Firstly, Ioc is InversionofControl. The translation is inversion of control, which means that the relationships between objects are no longer controlled by traditional programs. Instead, the Spring container has unified control over the creation, coordination, and destruction of objects that only need to complete the business logic.
IoC (InversionofControl) is at the heart of spring, throughout. IoC, for the Spring framework, means that Spring is responsible for controlling the life cycle of objects and the relationships between objects. For example, how do we find girlfriends? Common situation is, we go everywhere to see where there is a beautiful figure and good MM, and then inquire about their interests, QQ number, telephone number… Find a way to get to know them, give them what they want, and heh heh… The process is complex and profound, and we have to design and face each step ourselves. In traditional program development, if you want to use another object in an object, you have to get it (new one yourself, or look it up from JNDI) and then destroy the object (Connection, etc.). The object is always coupled with other interfaces or classes.
One focus of IoC is to dynamically provide one object with the other objects it needs while the system is running. This is done through DI (DependencyInjection). For example, object A needs to operate on the database. In the past, we always had to write code in A to get A Connection object. With Spring, we just need to tell Spring that A needs A Connection. When the system is running, Spring will make A Connection at the appropriate time and inject it into A like A needle, thus completing control over the relationships between objects. A relies on Connection to function properly, and this Connection is injected into A by Spring, hence the dependency injection name. So how is DI implemented? An important feature after Java1.3 is reflection, which allows applications to dynamically generate objects, execute object methods, and change object properties at runtime. Spring uses reflection to implement injection.
Let’s take a look at how Spring works
public static void main(String[] args) {
ApplicationContext context = new FileSystemXmlApplicationContext(
“applicationContext.xml”);
Animal animal = (Animal) context.getBean(“animal”);
animal.say();
}
This code is familiar to you, but let’s examine it, starting with ApplicationContext.xml
He has a class PHZ. Springframework. Test. The Cat
public class Cat implements Animal {
private String name;
public void say() {
System.out.println(“I am ” + name + “!” );
}
public void setName(String name) {
this.name = name;
}
}
Implements PHZ. Springframework. Test. The Animal interface
public interface Animal {
public void say();
}
Obviously the above code outputs Iamkitty! So how does Spring do it? Let’s write our own Spring to see how Spring works. First, we define a Bean class that holds properties owned by a Bean
/* Bean Id */
private String id;
/* Bean Class */
private String type;
/* Bean Property */
private Map<String, Object> properties = new HashMap<String, Object>();
A Bean contains id, Type, and Properties.
Spring then starts loading our configuration file, storing our configured information in a HashMap where the key is the Bean Id and the HasMap value is the Bean, Only then can we get the animal class through the context.getBean(“animal”) method. We all know that Spirng can inject primitive types, and can inject types like List and Map. Let’s take a look at how Spring saves maps
The Map configuration can look like the following
1
2
How does Spring save this configuration? , the code is as follows:
(beanProperty.element(“map”) ! = null) {
Map<String, Object> propertiesMap = new HashMap<String, Object>();
Element propertiesListMap = (Element) beanProperty
.elements().get(0);
Iterator<? > propertiesIterator = propertiesListMap
.elements().iterator();
while (propertiesIterator.hasNext()) {
Element vet = (Element) propertiesIterator.next();
if (vet.getName().equals(“entry”)) {
String key = vet.attributeValue(“key”);
Iterator<? > valuesIterator = vet.elements()
.iterator();
while (valuesIterator.hasNext()) {
Element value = (Element) valuesIterator.next();
if (value.getName().equals(“value”)) {
propertiesMap.put(key, value.getText());
}
if (value.getName().equals(“ref”)) {
propertiesMap.put(key, new String[] { value
.attributeValue(“bean”) });
}
}
}
}
bean.getProperties().put(name, propertiesMap);
}
The idea of dependency injection is very simple. It is implemented through reflection. When instantiating a class, it uses reflection to call the set method in the class to inject the class properties previously stored in the HashMap. Let’s see how it works. First instantiate a class like this
public static Object newInstance(String className) {
Class<? > cls = null;
Object obj = null;
try {
cls = Class.forName(className);
obj = cls.newInstance();
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
return obj;
}
And then it injects a dependency for that class, like this
public static void setProperty(Object obj, String name, String value) {
Class<? extends Object> clazz = obj.getClass();
try {
String methodName = returnSetMthodName(name);
Method[] ms = clazz.getMethods();
for (Method m : ms) {
if (m.getName().equals(methodName)) {
if (m.getParameterTypes().length == 1) {
Class<? > clazzParameterType = m.getParameterTypes()[0];
setFieldValue(clazzParameterType.getName(), value, m,
obj);
break;
}
}
}
} catch (SecurityException e) {
throw new RuntimeException(e);
} catch (IllegalArgumentException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
}
And finally it gives us an instance of this class, and we can use it. Using Map as an example, I wrote code to create a HashMap and inject the HashMap into the class to be injected, like this:
if (value instanceof Map) {
Iterator entryIterator = ((Map) value).entrySet()
.iterator();
Map<String, Object> map = new HashMap<String, Object>();
while (entryIterator.hasNext()) {
Entry entryMap = (Entry) entryIterator.next();
if (entryMap.getValue() instanceof String[]) {
map.put((String) entryMap.getKey(),
getBean(((String[]) entryMap.getValue())[0]));
}
}
BeanProcesser.setProperty(obj, property, map);
}