IOC
Inversion of Control 译为控制反转,是一种设计思想,Spring通过IOC容器来管理所有的Java对象的实例化和初始化,控制对象与对象之间的依赖关系。
由IOC管理的Java对象被称为Spring Bean,他们与通过new关键字创建出来的Java对象没有任何区别。
一个类想要使用另一个类的属性,就需要使用new关键字将后者的对象实例创建出来才能实现属性和方法的调用。即调用者控制着被调用者对象创建的控制权。
在Spring应用中,Java对象创建的控制权是掌握在IOC容器里的,大致步骤如下:
- 开发人员通过XML、注解、配置文件等方式将Java对象进行定义。
- 当Spring启动时,IOC容器会自动的根据据对象定义将对象创建并管理起来,这个由IOC容器管理的实例被称之为Spring Bean。
- 当需要某个Bean时,直接从IOC容器中获取即可,而不需要通过new关键字创建。
控制反转:原本调用者是主动的一方,即需要上面资源直接通过new关键字创建。但是在Spring中,IOC容器掌握着主动权,调用者成了被动的一方,被动的等待IOC容器来创建它所需要的对象。
DI
Denpendency Injection 译为依赖注入,Martin Fowler 在 2004 年在对“控制反转”进行解释时提出的。Martin Fowler 认为“控制反转”一词很晦涩,无法让人很直接的理解“到底是哪里反转了”,因此他建议使用“依赖注入”来代替“控制反转”。
依赖关系是一个对象需要用到另外一个对象,即该对象中存在一个属性在另一个对象。Spring在创建对象的过程中会根据依赖关系,将它依赖的对象也注册到IOC容器中。
依赖注入本质上是Spring Bean属性注入的一种,只不过这个属性是对象的属性。
IOC工作原理
IOC底层通过工厂模式、反射、XML解析等技术来降低代码的耦合度
- 在配置文件中对各个对象以及他们之间的依赖关系进行配置。
- IOC容器作为一个工厂,Bean就是产品。
- Spring在启动时会加载并解析配置文件,得到对象和他们之间的依赖关系。
- IOC利用反射,根据类名生成相应的对象,并根据依赖关系将这个对象注入到他依赖的对象中。
Spring是怎样设计容器的?
使用 ApplicationContext
,它是 BeanFactory
的子类,更好的补充并实现了 BeanFactory
的。
BeanFactory
简单粗暴,可以理解为 HashMap:
-
Key – bean name
-
Value – bean object
但它一般只有 get, put 两个功能,所以称之为“低级容器”。
而 ApplicationContext
多了很多功能,因为它继承了多个接口,可称之为“高级容器”。在下文的搭建项目中,我们会使用它。
ApplicationContext
的里面有两个具体的实现子类,用来读取配置配件的:
-
ClassPathXmlApplicationContext
– 从 class path 中加载配置文件,更常用一些; -
FileSystemXmlApplicationContext
– 从本地文件中加载配置文件,不是很常用,如果再到 Linux 环境中,还要改路径,不是很方便。
当我们点开 ClassPathXmlApplicationContext
时,发现它并不是直接继承 ApplicationContext
的,它有很多层的依赖关系,每层的子类都是对父类的补充实现。
而再往上找,发现最上层的 class 回到了 BeanFactory
,所以它非常重要。
代码演示
hello接口
public interface HelloMapper {
void sayHello();
}
hello接口实现类 —- 业务类
public class HelloMapperImpl implements HelloMapper{
@Override
public void sayHello() {
System.out.println(" something !!!");
}
}
测试类
@Test
public void test(){
HelloMapper helloMapper = new HelloMapperImpl();
helloMapper.sayHello();
}
执行结果
这是使用传统方式编写的代码,HelloMapperImpl 需要实现接口 HelloMapper,而测试类 test 需要依赖 HelloMapperImpl 这个业务类。所以测试类中就需要创建这个业务类的实例,然后才可以在测试类中使用。
Spring写法
<?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">
<!-- bean就是java对象实例, 即Spring创建和管理的不是类型而是实例 -->
<!-- Spring配置文件中的bean其实应该写在Java程序代码中,这段代码通常是new一个对象实例 -->
<bean id="hello" class="mapper.HelloMapperImpl"/>
</beans>
测试类
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
HelloMapper hello = context.getBean("hello", HelloMapper.class);
hello.sayHello();
}
Spring使用步骤:
- 找到配置文件。
- 加载配置文件。
- 解析配置文件中的bean元素,并识别id和class。
- 通过反射(Class.forName().newInstance())创建这个bean的实例。
- 将id作为key、实例作为value存放进Spring容器中。
- getBean取出实例
HelloMapper hello = context.getBean("hello", HelloMapper.class);
// 等价于
HelloMapper hello = class.forName("mapper.HelloMapperImpl").newInstance();
即根据配置文件 <bean> 中的 class属性值通过反射创建对象实例,并将 <bean> id 作为key,实例作为 value 保存在IOC容器中。在需要使用的时候直接从IOC容器中就可以获取到对象实例,而不需要通过new关键字的方式主动获取所依赖的对象实例,即获取对象实例的控制权反转了,不再是主动new,而是从第三方(IOC容器)中获取。
总结
所有的类都会在Spring容器中登记,告诉Spring你是个什么东西,你需要什么东西,然后spring会在系统运行到适当的时候,把你要的东西主动给你,同时也把你交给其他需要你的东西。
所有的类的创建、销毁都由 Spring来控制,也就是说控制对象生存周期的不再是引用它的对象,而是Spring。对于某个具体的对象而言,以前是它控制其他对象,现在是所有对象都被spring控制,所以这叫控制反转。
IOC的一个重点是在系统运行中,动态的向某个对象提供它所需要的其他对象。这一点是通过DI(Dependency Injection,依赖注入)来实现的。
控制反转IOC(Inversion of Control)是说创建对象的控制权进行转移,以前创建对象的主动权和创建时机是由自己把控的,而现在这种权力转移到第三方。
DI(依赖注入)其实就是IOC的另外一种说法,控制的什么被反转了?就是:获得依赖对象的方式反转了。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由半码博客整理,本文链接:https://www.bmabk.com/index.php/post/95908.html