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.类与类之间的关系:

  1. 继承(官方名称:泛化)
  2. 实现
  3. 依赖:类和类之间的关系是偶然的,临时的.在代码层面另一个类当作这个类的方法参数或局部变量
  4. 关联:类与类之间存在一定联系,可以是单向联系可以是双向联系.例如:学生和老师. (平时理解关联是一种强依赖),体现在代码层面,另一个类是这个类的全局属性.
  5. 聚合:类与类之间是可以单独存在的.但是有存在整体和部分的关系.例如:机箱和CPU.体现在代码层面:另一个类是这个类的全局属性.
  6. 组合:类与类之间是整体和部分之间的部分,不可分.例如人和心脏.体现在代码层面:另一个类是这个类的全局属性.
  7. 关系强度:组合 > 聚合 > 关联 > 依赖

3.DI的意义

  • 解除类与类之间高耦合性.

4.为什么称DI和IoC是同一个事情

  • (1)Spring帮助创建对象的过程叫做IoC,创建对象时给对象中全局对象赋值叫做DI,所以认为IoC和DI是同一个事情;
  • (2)再者,他们都可以通过一个<bean>标签实现;<bean>标签中,id属性只是这个标签的名字,叫啥无所谓,能记住就行;class属性是要为哪个类创建对象,或者为哪个类的属性注入值。  <bean>标签中的子标签<property>标签,是通过类的属性的set()方法来给类的属性注入值的;属性的数据类型是基本数据类型+String,那么使用value;属性的数据类型是引用,那么使用ref;(所以,在使用<property>子标签时,一定要确保类的这个属性有set()方法!)
  1. 代码实现

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>

 

 

 

猜你喜欢

转载自www.cnblogs.com/EricShen/p/11758099.html