Spring IOC原理,Spring容器,IOC容器以及Spring中的DI
一、Spring IOC原理
1.IOC定义
- IOC(Inversion of Control):即“控制反转”,意味着将设计好的对象交给容器控制;
- 传统的java程序设计,直接在对象的内部通过New形式创建对象,是程序主动去创建依赖对象,而IOC技术是专门的一个容器来创建对象,IOC容器来控制对象的创建而不是显性的使用new;
- 对象的创建交给容器管理,这就是控制反转;
- 控制反转是通过容器来完成的,Spring中提供了这样一个容器,称之为IOC容器;
- 无论是创建对象,处理对象之间的依赖,对象的创建时间还是创建的数量,都是由Spring为我们提供的IOC容器上配置上兑现信息就行;
2.IOC能做什么
- 有了IOC容器之后,对于使用方来说只需要进行调用就行了,把创建和查找依赖的对象的控制权交给了容器,由容器进行注入组合对象,所以对象与对象之间是松耦合的,这样方便进行测试,利用功能复用,使整个体系结构变得非常灵活;
- 由IOC容器来帮助对象找响应的依赖对象并注入,而不是对象主动去找,核心点在与资源不是有使用资源的调用方管理,而是不使用资源的第三方管理,第三方指的就是IOC容器;
- 资源的集中管理,实现资源的可配置和易管理;降低了使用 资源双方的依赖程度,也就是说松耦合;
3.Spring容器管理对象
1.添加Spring核心组件
2.Spring配置文件
3.创建实体类(xxx.java)
4.IOC容器管理对象
- 增加一个Spring配置文件;
- 对xml配置文件进行解析(bean标签)
- BeanFactory工厂类
- 在工厂类的方法中使用反射创建Bean对象
4.IOC容器
- ApplicationContext接口是BeanFactory的子接口;
- BeanFactory是Spring IOC容器所定义的最底层接口;
- ApplicationContext是BeanFactory的最高级实现之一,并对BeanFactory功能上做了很多的扩展,所以大部分的工厂场景下,都会使用ApplicationContext作为IOC容器;
1、 BeanFactory
1. 最底层的实现,提供了比较先进的配置机制,使得任何对象的配置成为可能;
- ApplicationContext:
1. 在BeanFactory的基础上做了很多扩展实现;
- 区别:
1. BeanFactory的实现是按需创建,即第一次获取bean时创建bean;
2. ApplicationContext会一次性创建所有的bean,ApplicationContext也创建了一些额外的功能,比如与Spring的AOP更容易继承,也提供了Message Resource的机制(用于处理国际化支持)和通知机制;
2、 ApplicationContext的常用实现类
- ClassPathXmlApplicationContext
- 读取classpath,如果配置文件在当前系统类路径下,可以优先使用ClassPathXmlApplicationContext类
- FileSystemXmlApplicationContext
- 读取指定路径下的资源,如果配置文件放在文件系统路径下,则可以优先使用ClassPathXmlApplicationContext类;
3、 容器管理对象
4、 Spring中Bean的实例
1.基于XML的配置方式转配Bean
- 无参构造方法实例化对象
- 如果不指定构造函数,会生成一个默认的无参构造函数;
- 如果显性的指定有参构造函数,不会生成默认的构造函数,必须显性指定一个无参构造函数
- 静态工厂类实例化对象
- 普通工厂实例化对象
-
通过工厂创建一个非静态方法得到对象;
-
配置文件中时同工厂的非静态方法返回对象;
-
2.基于注解方式装配Bean(自动装配)
- 基于注解形式进行bean的管理比bean
3.通过java代码装配Bean(组件扫描)
-
给定一个配置类,在配置类上添加Configuration注解表明当前类是一个配置类,告诉Spring应用上下如何创建Bean细节;
-
将交给spring管理的类声明为bean,编写一个方法,方法会创建所需要的bean的实例,给方法添加上@bean注解;
-
@bean注解会告诉spring这个方法
二、Spring中DI
- DI(Dependency Injection):即依赖注入,对象之间的依赖由容器在运行期决定,即容器动态的将某个依赖注入到对象中;
1、基于XML配置注入依赖
1. 有参构造函数注入依赖
1. bean类实现有参构造函数;
public class Student{
private Integer id;
private String name;
/**
*有参构造函数
*/
public Student(Integer id,String name){
this.id=id;
this,name=name;
}
}
2.在配置文件中配置参数通过有参构造函数给对象属性赋值;
<!--通过有参构造注入依赖-->
<bean id="student" class="com.wang.Spring.IOC.POJO.Student">
<!--id属性注入-->
<constructor-arg name="id" value="11"/>
<!--name属性注入-->
<constructor-arg name="name" value="wang"/>
</bean>
3. 有参构造函数使用constructor-arg标签
2. set方法注入依赖
1. 给对象的属性提供setter方法
public class Student{
private Integer id;
private String name;
public void setId(Integer id){this.id=id;}
public void setName(Strign name){this.name=name;}
}
2. 在配置文件中通过set方法赋值
<!--通过setter方法注入依赖-->
<bean id="student" class="com.wang.Spring.IOC.PoJo.Student">
<property name="id" value="12"/>
<property name="name" value="java"/>
</bean>
3. 通过set方法使用的是property标签
3. 注入依赖也可以是自定义类型
<!--注入自定义类型-->
<bean id="user" class="com.wang.Spring.IOC.PoJo.user">
<constructor-arg name="name" value="java"/>
</bean>
<bean id="student" class="com.wang.Spring.IOC.PoJo.student">
<property name="id" value="12"/>
<property name="name" value="java"/>
<!--value属性:将参数按照Syringe类型进行解析 ref类型:String中管理对象的id值-->
<property name="user" ref="user"/>
</bean>
自定义类型也是要交给spring进行管理,如何后去管理对象实例
1.使用ref属性来获取值,该ref会自动识别为spring中对象的名字
2.使用value属性来获取值,spring会认为仅仅是一个字符串值
4. 依赖也可以是集合类型
<!--注入集合类型-->
<bean id="student" class="com.wang.Spring.IOC.PoJo.Student">
<!--注入list类型-->
<property name="bookName">
<list>
<value>语文</value>
<value>数学</value>
<value>英语</value>
</list>
</property>
<!--注入map类型-->
<property name="bookName">
<map>
<entry key="语文" value="99"/>
<entry key="数学" value="92"/>
</map>
</property>
</bean>
2、基于注解形式注入依赖
@value:注入普通类型属性
@Resource:注入对象类型
@Autowired:注入对象类型
@value
- 该注解只能添加到普通类型上,@Value(“1”)注解中可以赋值完成对基础属性的依赖注入
@Component(value=student")
public class Student{
@Value("1")
private Integer id;
}
@Resource
- 该注解注入对象类型
- 是由java提供的,而不是由Spring框架提供,默认按照类型查找并注入类
@Component(value="student")
public class Student{
//自定义类型
@Resource(name="user")
private User user;
}
@Autowired
- 注入对象类型,是Spring框架提供的,按照名称来注入
@Component(value="student")
public class Student{
//自定义类型
@Autowired
private User user;
}
@Autowired和Resource的异同点
- 联系
- @Autowired和@Resource注解都是作为bean对象注入的时候使用的
- 两者都可以声明在字段和setter方法上
- 如果生命在字段上,那么就不需要再写setter方法,但是本质上该对象还是作为set方法的实参,通过执行set方法注入,知识省略了setter方法罢了。
- 区别
- @Autowired注解是Spring提供的,而@Resource注解是J2EE本身提供的
- @Autowired注解是默认通过byType方式注入,而@Resource注解是默认通过byName方式注入
- @Autowired注解注入的对象需要早IOC容器中存在,否则需要加上属性required=false,表示忽当前要注入的bean,如果有直接注入,没有则跳过。
- byName就是变量名去匹配bean的id属性,而不TYpe则是变量类型去匹配bean的class属性