什么是Spring的IOC
1、IOC是Inversion of Control简写,中文称之为控制反转
2、作用时将对象的创建权交由Spring框架去管理,在没用框架之前,创建对象是我们采用new xxx()来创建该对象,在Spring中对象的创建是交给IOC容器的,不需要我们自己去创建
3、作用是降低了代码的耦合度
SpringIOC创建对象
目标:
通过IOC创建对象,调用对象的中方法
1、整个项目目录
2、IDEA创建普通的maven项目,也可创建普通项目java项目导入架包
3、打开项目找到pom.xml文件配置如下主要是 <dependencies> </dependencies>里面的包
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>springNewBean</groupId>
<artifactId>work.chenc</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!-- junit测试包 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- spring-context 包含Spring必须的架包-->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
</dependencies>
</project>
spring-context 包含Spring必须的架包
4、新建一个类,并给类一个方法
package work.chenc.entity;
public class UserEntity {
public UserEntity() {
System.out.println("UserEntity无参构造----------------");
}
public void doSomething() {
System.out.println("UserEntity-doSomething........");
}
}
5、新建一个xml文件,位置可以自选,我选择的是在resources目录下
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--
id: getBean(id) 通过id获取实例化的对象
class: 需要创建对象的全路径-根据类的全路径获取类的class(字节码)
-->
<bean id="user" class="work.chenc.entity.UserEntity"></bean>
</beans>
6、Junit测试-调用UserEntity中的doSomething方法
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import work.chenc.entity.UserEntity;
public class NewBeanTest {
@Test
public void testIocNewBean() {
// 1、获取ApplicationContent对象解析xml文件并创建对象 - spring内部处理
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:bean.xml");
// 2、获取创建的对象
UserEntity userEntity = context.getBean("user", UserEntity.class);
userEntity.doSomething();
}
}
补充说明:通过执行结果可知、这里创建对象调用了类的无参构造方法,而我们New UserEntity() 默认也只调用无参构造
IOC底层原理
一、IOC之前创建对象的方法
通过图解可以看出原始方法对象之间的耦合性非常高,采用工厂虽然能降低UserDao和UserService之间的耦合性但是userFactory和UserService之间的耦合性还是非常高,为了解决这一情况,Spring为我们提供了IOC控制反转,他能进一步降低类与类之间的耦合性
IOC实现控制反转
实现IOC主要用到的技术:XML解析、工厂模式、反射
通过IOC创建对象的重点在与xml文件,如果类的路径发成改变,我们只需要修改对应的类的class属性即可,这样就大大的降低了代码之间的耦合性
IOC接口说明
1、IOC思想是基于IOC容器,IOC容器的底层实现就是对象工厂
2、Spring提供了两种实现IOC的方式
a.BeanFactory:IOC容器的基本实现,是Spring内部使用的接口,不提供开发人员使用
b.ApplicationContext: BeanFactory接口的子类,提供了更强大的功能,一般供开发人员使用
区别:
BeanFactory在加载配置文件时,不会创建对象,再获取对象(使用)对象的时候才会创建
ApplicationContext在加载配置文件时就会创建对象(项目启动加载配置文件就会创建对象)
3、ApplicationContext接口的实现类
FileSystemXmlApplicationContext:这里路劲必须系统绝对路径
ClassPathXmlApplicationContext:这里src下的路径
// 1、根据ApplicationContent 上下文对象解析并加载配置文件bean.xm 在src目录下
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
ApplicationContext context = new FileSystemXmlApplicationContext("系统下的绝对路径");
补充:
蓝色的实线===》类继承类
绿色的实线===》 接口继承接口
绿色的虚线===》 类实现接口
由上图可以确定 ApplicationContent的确BeanFactory的子类,FileSystemXmlApplicationContext及ClassPathXmlApplicationContext都是ApplicationContext的实现类
简单实现通过配置文件及反射创建对象并调用对象方法
这里需要一个dom4j
架包,我这里直接使用的Maven创建的普通项目,测试用的junit架包,这是我的pom.xml引入的架包
ps:dom4j在解析xml需要用到
<dependencies>
<!-- 测试包 -->
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- 引入dom4j -->
<!-- https://mvnrepository.com/artifact/dom4j/dom4j -->
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
</dependencies>
1、创建一个UserDao类,代码如下
public class UserDao {
public void find() {
System.out.println("------------执行了UserDao.find()方法------------");
}
}
2、创建一个bean.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="user" class="entity.UserDao"></bean>
</beans>
3、核心代码
// 1、获取文件 - 绝对路径
File file = new File("/Users/chenlibrary/Documents/project/chenlibrary/SpringIOC_demo/src/main/resources/bean.xml");
// 相对路径
// File file = new File("src/main/resources/bean.xml");
// 2、获取文件流
FileInputStream inputStream = new FileInputStream(file);
// 3. 创建SAXReader对象
SAXReader reader = new SAXReader();
// 4、获取文件Document对象
Document doc = reader.read(inputStream);
// 获取文件节点
Element root = doc.getRootElement();
// 获取文件中所有bean元素
List<Element> list = root.elements("bean");
// 迭代
if (list != null && list.size() > 0) {
for (Element bean : list) {
// 反射操作
Class clazz = Class.forName(bean.attributeValue("class"));
//生成对象
UserDao userDao = (UserDao) clazz.newInstance();
userDao.find();
}
}
File file = new File("XXXX"),这里可以根据xml的绝对路径或相对路径找到xml文件
绝对路径
window下及从盘符开始到xml文件的目录,我这里是mac下的绝对路劲
相对路径
是从当前项目的位置开始找的,下图是我的xml文件地址
这里只是简单的实现了IOC的中的通过解析xml配置,再通过反射获取配置文件中类的字节码文件在创建对象,至于工厂模式这里暂无涉及,待后续继续学习。