Spring—02—SpringIOC、DI;
IOC相当于帮我们创建对象;
DI相当于给创建好的对象的属性赋值;
ioc是目的,di是手段。所以上文的第一句话应该是错的,帮助我们创建对象的是applicationcontext
一、IOC解释
1、英文名称:(Inversion of Control)
2、中文名称:控制反转
(1)控制:对类实例化的控制.指的是创建对象这个事情.
(2)反转:以前由程序员实例化的过程, 转交给Spring进行实例化(程序员使用new关键字,SpringIOC使用反射机制);
3、通俗解释:由Spring帮助实例化对象,释放程序员对对象的关注度,所有的关注度都放在业务上.同时还可以达到解耦的效果;
4、项目应用场景:
(1) 帮助创建SqlSessionFactory
(2) 管理所有Mapper接口,管理所有ServiceImpl类;
5、SpringIOC优点:
实现了各层之间的解耦。如果new一个对象,当类改名字的时候,我们在controller层可能需要创建50个这个对象,那么当这个类的名字改变的时候,我们这50个创建对象的方法都需要改变,非常的麻烦,而且容易出错,这个时候,我们使用控制反转,在xml文件里,配置<bean>标签,让工厂替我们创建50个对象,我们只需要在测试类中获取已创建好的对象就可以;
二、使用IOC创建对象:
1、使用SpringIOC创建对象一共有三种:
- 使用<bean>标签无参构造类的对象;然后在测试类中解析xml.文件,获得app对象,然后就可以通过调用getBean()方法获取一个或多个本类的对象了;
- 使用<bean>标签有参构造一个对象;在<bean>标签调用<constructor>子标签,将参数传递;
- 使用<bean>标签构造一个工厂类的对象,通过工厂类对象,调用工厂类对象中的成员方法;(IOC是使用了反射的技术来动态的生成对象;工厂模式的对象生成是提前在工厂类中定死的)
2、无参数构方式
创建对象的默认方式;
3、有参构造方式
构造器中的name属性和实体类有参构造方法中形参名字保持一致;
还可以在构造器中使用三个属性:
- index: 从0开始的索引
- name: 构造方法参数名称
- type: 构造方法参数类型,支持类型关键字(int)
- 如果上面三个属性都写支持,更加精确告诉Spring使用哪个构造方法.
4、实例工厂:
我们使用IOC不是替代工厂模式,只是通过xml文件代替了创建Factory类的过程;而工厂模式中的工厂类还是一样的;
三、DI:依赖注入
1.解释
英文全称(Dependency Injection)
中文名称: 依赖注入
- 依赖:一个类在另一个类中作为全局属性时
- 注入:通过外部给自己属性(或其他内容)进行赋值
2.类与类之间的关系:
- 继承(官方名称:泛化)
- 实现
- 依赖:类和类之间的关系是偶然的,临时的.在代码层面另一个类当作这个类的方法参数或局部变量
- 关联:类与类之间存在一定联系,可以是单向联系可以是双向联系.例如:学生和老师. (平时理解关联是一种强依赖),体现在代码层面,另一个类是这个类的全局属性.
- 聚合:类与类之间是可以单独存在的.但是有存在整体和部分的关系.例如:机箱和CPU.体现在代码层面:另一个类是这个类的全局属性.
- 组合:类与类之间是整体和部分之间的部分,不可分.例如人和心脏.体现在代码层面:另一个类是这个类的全局属性.
- 关系强度:组合 > 聚合 > 关联 > 依赖
3.DI的意义
- 解除类与类之间高耦合性.
4.为什么称DI和IoC是同一个事情
- (1)Spring帮助创建对象的过程叫做IoC,创建对象时给对象中全局对象赋值叫做DI,所以认为IoC和DI是同一个事情;
- (2)再者,他们都可以通过一个<bean>标签实现;<bean>标签中,id属性只是这个标签的名字,叫啥无所谓,能记住就行;class属性是要为哪个类创建对象,或者为哪个类的属性注入值。 <bean>标签中的子标签<property>标签,是通过类的属性的set()方法来给类的属性注入值的;属性的数据类型是基本数据类型+String,那么使用value;属性的数据类型是引用,那么使用ref;(所以,在使用<property>子标签时,一定要确保类的这个属性有set()方法!)
- 代码实现
6.1 在一个类中放置另一个类的对象
public class People { private int id; private String name; private String address; private Classroom classroom; |
6.2 在applicationContext.xml创建Classroom对象,把对象注入People
6.2.1 如果类中属性是一个对象时使用ref属性引用另一个<bean>的id
<bean id="classroom" class="com.bjsxt.pojo.Classroom"> <property name="id" value="1"></property> <property name="name" value="C01"></property> </bean> <bean id="peo" class="com.bjsxt.pojo.People"> <!-- 设值注入,通过set方法给属性赋值 --> <property name="id" value="123"></property> <property name="name" value="张三"></property> <property name="classroom" ref="classroom"></property> </bean> |
四、三种注入方式
1、构造注入:
实体类中提供有参构造方法,然后在applicationContex.xml文件中通过<bean>标签的<constructor-arg>注入:
2、设值注入:执行属性的set()方法
- <bean>标签中,id属性只是这个标签的名字,叫啥无所谓,能记住就行;class属性是要为哪个类创建对象,或者为哪个类的属性注入值。
- <bean>标签中的子标签<property>标签,是通过类的属性的set()方法来给类的属性注入值的;属性的数据类型是基本数据类型+String,那么使用value;属性的数据类型是引用,那么使用ref;(所以,在使用<property>子标签时,一定要确保类的这个属性有set()方法!)
和构造注入相比,主要是一个使用了<constructor>标签,它需要实体类提供相应的有参构造方法;
另外一个使用了<property>标签,它需要实体类提供每个属性的set()方法;
3、自动注入
2.3.1 通过<bean>的autowire属性控制类中属性自动注入方式(autowire="byName"或者autowire="byType")
2.3.2 autowire可取值:
2.3.2.1 no: 不自动注入
2.3.2.2 default: 默认值.看全局<beans>的default-autowire属性的值
2.3.2.3 byName:通过名称自动注入.只能自动注入对象,而无法注入String或基本数据类型或value属性复制东西.
<bean id="classroom" class="com.bjsxt.pojo.Classroom"> <property name="id" value="1"></property> <property name="name" value="C01"></property> </bean> <bean id="address" class="java.lang.String"> <constructor-arg type="java.lang.String" value="abc"></constructor-arg> </bean> <bean id="peo" class="com.bjsxt.pojo.People" autowire="byName"> </bean> |
2.3.2.4 byType:通过类型自动注入.通过属性的类型去applicationContext.xml中找<bean>的class属性.依然对通过value赋值的属性无效.
2.3.2.5 constructor:通过构造自动注入.有参构造中参数必须在ApplicationContext中都找到.
public People(String name, String address, Classroom classroom) { super(); this.name = name; this.address = address; this.classroom = classroom; } |
<bean id="classroom" class="com.bjsxt.pojo.Classroom"> <property name="id" value="1"></property> <property name="name" value="C01"></property> </bean> <bean id="address" class="java.lang.String"> <constructor-arg type="java.lang.String" value="abc"></constructor-arg> </bean> <bean id="name" class="java.lang.String"> <constructor-arg type="java.lang.String" value="张三"></constructor-arg> </bean> <bean id="peo" class="com.bjsxt.pojo.People" autowire="constructor"></bean> |
2.4 default-autowire和autowire区别
2.4.1 default-autowire配置<beans>当前xml文件所有<bean>都使用这种注入方式
2.4.2 autowire:配置<bean>只针对这个<bean>生效
2.4.3 如果配置了default-autowire和autowire时候,autowire生效.
十.设值注入时,不同数据类型的注入方式
String或基本数据类型等
<bean id="classroom" class="com.bjsxt.pojo.Classroom"> <property name="id" value="1"></property> </bean> |
属性是对象类型
<bean id="peo" class="com.bjsxt.pojo.People"> <property name="classroom" ref="classroom"></property> </bean> |
属性是数组时,和list可以相互替换
属性是List集合时,可以和array相互替换
属性是Set集合时 (set集合具有无序性、唯一性),我们给集合赋值了A、A、B、C,最后在console打印的时候,还是只有A、B、C;
属性是Map集合时
属性是Properties类型时,用spring配置文件配置出.properties文件的效果.
<property name="pro"> <props> <prop key="key">value</prop> </props> </property> |