Spring IOC
what’s Spring IOC?
控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)
DI是实现IOC的一种技术手段。就像ORM和Mybatis的关系一样(关系映射)。
书面的理解:
Spring IoC容器负责对象的生命周期和对象之间的(依赖)关系。
在创建新的Bean时,IoC容器会自动注入新Bean的所依赖的其他Bean,而无须自己手动创建。![]()
- IoC容器自动完成对象的初始化,避免在开发过程中写一大段初始化代码。
- 创建实例的时候不需要了解细节。
什么是依赖查找?
其中JNDI就是依赖查找的一种实现方式,可以参考博客:JNDI学习总结(一)——JNDI数据源的配置
也就是我们在Tomcat中配置了一个数据源,在通过某种方式将它拿出来使用,并不是再代码中new
出来的,这里不再细说,感兴趣的还可以去了解下什么是依赖查找和依赖拖拽
。
那什么又是依赖呢?
通常我们会在类A中写类B,这时候我们就会说类A依赖B,因为如果没有类B我们的类A将不能正常使用。
那什么又是依赖注入呢,参考博客 什么是依赖注入
为什么要使用spring IOC
spring体系结构——IOC的位置 自己看官网
在日常程序开发过程当中,我们推荐面向抽象编程,面向抽象编程会产生类的依赖,当然如果你够强大可以自己写一个管理的容器,但是既然spring以及实现了,并且spring如此优秀,我们仅仅需要学习spring框架便可。
当我们有了一个管理对象的容器之后,类的产生过程也交给了容器,至于我们自己的app则可以不需要去关系这些对象的产生了。
spring实现IOC的思路和方法
spring实现IOC的思路是提供一些配置信息用来描述类之间的依赖关系,然后由容器去解析这些配置信息,继而维护好对象之间的依赖关系,前提是对象之间的依赖关系必须在类中定义好,比如A.class中有一个B.class的属性,那么我们可以理解为A依赖了B。既然我们在类中已经定义了他们之间的依赖关系那么为什么还需要在配置文件中去描述和定义呢?
spring实现IOC的思路大致可以拆分成3点
- 应用程序中提供类,提供依赖关系(属性或者构造方法)
- 把需要交给容器管理的对象通过配置信息告诉容器(xml、annotation,javaconfig)
- 把各个类之间的依赖关系通过配置信息告诉容器
配置这些信息的方法有三种分别是xml,annotation和javaconfig
维护的过程称为自动注入,自动注入的方法有两种构造方法和setter
自动注入的值可以是对象,数组,map,list和常量比如字符串整形等
spring编程的风格
- 注解式开发 annotation-based——-annotation
- 配置文件 schemal-based———-xml
java配置 java-based——java Configuration
Ioc的三种装配方法
依赖注入的本质就是装配,装配是依赖注入的具体行为。这就是两者的关系
①:set注入
基本数据类型注入 集合注入 对象注入
②: 构造注入
基本数据类型注入
③: 自动装配
注入的两种方法
Spring3中提供接口注入的方法,但是不符合设计等原因,在后续的版本中取消掉了,
因此我们可以认为spring中注入有两种方法
。
官方:spring注入详细配置(字符串、数组等)参考文档Constructor-based Dependency Injection(构造方法注入)
官方:构造方法注入参考文档
下面是简单的一个例子,如果需要详细的解释,请查看上面提供的官方文档public class SimpleMovieLister { // the SimpleMovieLister has a dependency on a MovieFinder private MovieFinder movieFinder; // a constructor so that the Spring container can inject a MovieFinder public SimpleMovieLister(MovieFinder movieFinder) { this.movieFinder = movieFinder; } // business logic that actually uses the injected MovieFinder is omitted... }
Setter-based Dependency Injection(setter方法注入)
官方:setter参考文档
自动装配
上面说过,IOC的注入有两个地方需要提供依赖关系,一是类的定义中(即A类中定义有B类,并且A中需要有Setter方法或者构造方法),二是在spring的配置中需要去描述(描述两个类的关系,这样spring才能完成注入)。自动装配则把第二个取消了,但是还需要A中有Setter方法或者构造方法。
例子(没有自动装配)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd"
>
<bean id = "dao" class="dao.IndexDaoImp"></bean>
<bean id="indexService" class="dao.IndexService">
<property name="dao" ref="dao"></property><!--这里我们描述了两个类的依赖关系-->
<!--在实际开发中,这里面要写很多的,像上面一样的关系,大家可以看到用xml装配bean是一件很繁琐的事情,而且我们还要找到对应类型的bean才能装配。因此有了自动装配-->
</bean>
</beans>
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
public class IndexService {
private IndexDao dao;
void test() {
System.out.println("service");
dao.test();
}
public void setDao(IndexDaoImp dao) {//这里提供了set方法
this.dao = dao;
}
}
例子(自动装配)
添加default-autowire="byType"
,下面会说明含义
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd"
default-autowire="byType">
<bean id = "indexDao" class="dao.IndexDaoImp"></bean>
<bean id="indexService" class="dao.IndexService"> </bean>
</beans>
在实际开发中,描述类之间的依赖关系通常是大篇幅的,如果使用自动装配则省去了很多配置,并且如果对象的依赖发生更新我们可以不需要去更新配置,但是也带来了一定的缺点
官方:自动装配的优点参考文档 和 缺点参考文档
自动装配的方法
官方:自动装配的方式参考文档
推荐看这个博客:Spring IOC-自动装配xml方式
- no
- byName
- byType
- constructor
byType按被注入对象的类型相同的进行注入(为属性赋值调用set方法)
byName按与被注入对象id与set方法名相同的进行注入
constructor(与byType类似)按构造方法中被注入对象的类型相同的注入
spring懒加载
官网已经解释的非常清楚了:
https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-factory-lazy-init
值得提醒的是,如果你想为所有的对都实现懒加载可以使用官网的配置
springbean的作用域
文档参考:
https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-factory-scopes
Singleton Beans with Prototype-bean Dependencies
意思是在Singleton 当中引用了一个Prototype的bean的时候引发的问题
官网引导我们参考https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-factory-method-injectio
这里不再多说了,动手了才知道,内容是真的多!!!容我慢慢道来。