IoC底层原理
前沿:
- 控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来降低代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。IoC可以认为是一种全新的设计模式,但是理论和时间成熟相对较晚,并没有包含在GoF中。
- Class A中用到了Class B的对象b,一般情况下,需要在A的代码中显式的new一个B的对象。
采用依赖注入技术之后,A的代码只需要定义一个私有的B对象,不需要直接new来获得这个对象,而是通过相关的容器控制程序来将B对象在外部new出来并注入到A类里的引用中。而具体获取的方法、对象被获取时的状态由配置文件(如XML)来指定。 也就是说把对象创建和对象之间的调用过程,交给了Spring进行管理。
一. 底层主要用到的技术
- xml解析
- 工厂模式
- 反射
现在我们开始讲解:
先看如下代码:
public class Person {
public void eat(){
System.out.println("吃饭!");
}
}
- 1
- 2
- 3
- 4
- 5
- 6
public class Student {
private Person person = new Person();
public void eatForStudent(){
person.eat();
System.out.println("喝牛奶!");
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
在Student类中需要用到Person,此时我们一般的做法是在Student类中new一个Person的对象,然后通过这个对象去调用其方法,但是我们是否想过,如果Person类发生的改变,比如类名发生了改变,类的路径发生了改变,假如说其他类中也创建了Person对象,如果在其他的类中也创建了Person类对象,这个时候就需要大量的改类路径或者名称,很麻烦了,这个时候我们可以用到如下的工厂模式去解决这个问题:
public class PersonFactory {
public static Person getPerson(){
return new Person();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
public class Student {
private Person person = PersonFactory.getPerson();
public void eatForStudent(){
person.eat();
System.out.println("喝牛奶!");
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
然后在Student类中去调用getPerson方法返回Person类对象,把创建对象的过程交给工厂类PersonFactory来做,如果其他类中也都调用PersonFactory类中的getPerson方法来获取Person类对象,那么如果Person的类路径或者类名改变了,也只需要改变一处即可,也就是改变getPerson方法中的类名称或类路径。
在用了工厂模式之还是有一定的耦合度,此时我们就需要我们的IOC原理,把耦合度降低到最低,在这个过程中除了用到工厂模式外,还需要用到xml解析加上反射。
二.IOC原理过程
步骤一:xml配置文件,配置创建的对象
<bean id="person" class="iocprinciple.Person"></bean>
- 1
步骤二:创建工厂类(在工厂模式的基础上利用xml解析加上反射来创建Person类的对象)
public class PersonFactory {
public static Person getPerson() throws Exception {
//Dom4j xml解析获取类的全路径
String classPath = new ClassPathXmlApplicationContext("bean1.xml").getClassPath("person");
//通过反射得到类的字节码文件
Class clazz = Class.forName(classPath);
//调用方法得到对象
Person person = (Person)clazz.newInstance();
return person;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
Person类内容不变,Student变为如下:
public class Student {
private Person person;
public void eatForStudent(){
try {
person = PersonFactory.getPerson();
} catch (Exception e) {
e.printStackTrace();
}
person.eat();
System.out.println("喝牛奶!");
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
用到Dom4j的xml解析类如下:
import java.io.InputStream;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
public class ClassPathXmlApplicationContext {
private String configFilePath;
public ClassPathXmlApplicationContext(String configFilePath) {
this.configFilePath = configFilePath;
}
/*
* dom4j解析
*/
public String getClassPath(String id) throws Exception {
String classPath = null;
// 解析xml
SAXReader reader = new SAXReader();
InputStream inputStream = ClassLoader.getSystemResourceAsStream(configFilePath);
Document document = reader.read(inputStream);
if (document == null) {
return null;
}
// 从项目根目录下读取
Element root = document.getRootElement();
// 获取节点资源
List<Element> list = root.elements();
if (list.size() <= 0) {
return null;
}
for (Element element : list) {
String idString = element.attributeValue("id");
if (id.equals(idString)) {
// 获取bean的class地址
classPath = element.attributeValue("class");
break;
}
}
return classPath;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
这就是spring中IoC的底层原理,在之后的使用过程中,我们只需要写好spring的xml配置文件就可以啦,Spring已经为我们写好了这些关于IoC底层的代码。
文章来源: blog.csdn.net,作者:Mr.Yushiwen,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/MrYushiwen/article/details/109953263
- 点赞
- 收藏
- 关注作者
评论(0)