目录
✅作者简介:Java-小白后端开发者 🥭公认外号:球场上的黑曼巴
🍎个人主页:不会飞的小飞侠24
🍊个人信条:谨 · 信
💞当前专栏:高级内容
🥭本文内容:JAVA -----mybatis框架【Spring】控制反转(IOC 】
更多内容点击👇
小飞侠的博客>>>>欢迎大家!!!
一 Ioc控制反转
1.1 概述
- IoC是英文Inversion of Control的缩写,是控制反转的意思,即调用者创建被调用者的实例对象不是由调用者自已完成,而是由Spring容器完成,并注入给调用者。
- 使用了IoC后,一个对象(调用者)依赖的其它对象(被调用者)会通过被动的方式传递进来,而不是这个对象(调用者)自己创建或者查找依赖对象(被调用者)。spring容器在对象初始化时不等对象请求就主动将依赖对象传递给它。IoC只是一种编程思想,具体的实现方法是依赖注入。
1.2 依赖注入
- 依赖注入(Dependency Injection,DI)是指程序运行过程中,若需要调用另一个对象协助时,无须在代码中用硬编码(如用new构造方法)创建被调用者,而是依赖于外部容器(如spring),由外部容器创建后传递给程序。依赖注入解决了传统的编程方法中类与类之间严重直接依赖的问题,是目前最优秀的解耦方式。依赖注入让Spring的Bean之间以配置文件的方式组织在一起,而不是以硬编码的方式耦合在一起的。
二 传统依赖的问题
2.1 在传统的项目中
- 会创建Dao service 结构,通过一个类依赖另外一个,修改时,牵一发 动全身。
引入一个依赖不利的因素
三 引入Spring解决
- 在项目spring2中导入Spring jar包
在pom.xml中引入依赖。- 创建Spring配置文件apllicationContext.xml,添加约束,实现创建实例化对象的功能。
- 修改RegisterService类,注释或删除掉regist()方法中创建RegisterDaompl实例的代码。
- 修改测试类
<bean id="user" class="cn.syb.spring01.entity.User" >
<property name="id" value="1"></property>
<!-- property 通过赋值操作,调用set方法-->
<property name="username" value="tom"></property>
<property name="password" value="122"></property>
</bean>
3.1 Spring配置文件中Bean属性
3.2 Bean的作用域
- 当通过Spring容器创建一个Bean 实例时,不仅可以完成Bean的实例化,还可以通过scope属性,为Bean 指定特定的作用域。Spring支持5种作用域。
- singleton:单例模式。在整个Spring容器中,使用singleton定义的Bean将是单例的,即只有一个实例,第二次以后调用的bean跟第一次调用的是同一个对象,默认为单例的,该Bean是在容器被创建时即被装配好了。
- prototype:原型模式。即每次使用getBean方法获取的同一个的实例都是一个新的实例。对于 scope为 * * prototype的原型模式,Bean实例是在代码中使用该Bean实例时才进行装配的。
- request:对于每次HTTP请求,都将会产生一个不同的Bean实例。
- session:对于每个不同的HTTP session,都将产生一个不同的Bean实例
3.3 项目案例
- 创建RegisterService类的两个bean,第一个bean的id是regService1,scope属性值是singleton,第二个bean的id是regService2,scope属性值是prototype。测试类中各getBean两次,观察每次获取到的对象是不是同一个对象
<!-- 相当于在程序中创建一个RegisterDaoImpl类的对象,对象名为registerDao -->
<bean id="registerDao" class="com.lifeng.dao.RegisterDaoImpl"/>
<!-- 相当于在程序中创建一个RegisterService类的对象,对象名为regService1 -->
<bean id="regService1" class="com.lifeng.service.RegisterService" scope="singleton">
<!-- 相当于为对象regService1中的registerDao属性注入实例 化对象registerDao -->
<property name="registerDao" ref="registerDao"/>
</bean>
<bean id="regService2" class="com.lifeng.service.RegisterService" scope="prototype">
<!-- 相当于为对象regService2中的registerDao属性注入实例 化对象registerDao -->
<property name="registerDao" ref="registerDao"/>
</bean>
Test
ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
RegisterService regService11=(RegisterService) context.getBean("regService1");
RegisterService regService12=(RegisterService) context.getBean("regService1");
System.out.println("regService11与regService12是否同一个对象:"+(regService11==regService12));
RegisterService regService21=(RegisterService) context.getBean("regService2");
RegisterService regService22=(RegisterService) context.getBean("regService2");
System.out.println("regService21与regService22是否同一个对象:"+(regService21==regService22));
四 基于xml的依赖注入(注意有参 无参的构建)
- Bean的依赖注入又称为bean的装配,即利用spring实现bean的实例化过程,在这个过程中需完成实例化对象的创建,并给对象的各个属性赋值等任务。Spring有多种bean的装配方式,包括基于xml文件的装配,基于注解的装配,自动装配。
- 其中基于xml文件的配置又分为两种装配方式:设值注入和构造注入。
- Spring实例化bean的时候,首先会调用bean的默认的无参构造方法来实例化一个空值的bean对象,接着对Bean对象的属性进行初始化,初始化是由spring容器自动完成的,称为注入
4.1 设置注入
- 是指Spring通过反射机制调用setter方法来注入属性值,bean必须满足以下两点要求才能被实例化:
- (1)Bean类必须提供一个无参的构造方法,注意如果程序员定义了有参的构造方法,则必须要显式的提供无参的构造方法。
- (2)属性需要提供setter方法
<bean id="user2" class="com.lifeng.entity.User">
<property name="uid">
<value>2</value>
</property>
<property name="uname">
<value>李四</value>
</property>
<property name="gender">
<value>女</value>
</property>
<property name="age">
<value>19</value>
</property>
</bean>
4.2 构造注入(依赖有参构造)
在constructor-arg 中,利用有参赋值时,注意与实体类属性顺序
<bean id="user3" class="com.lifeng.entity.User">
<constructor-arg name="uid" value="3"/>
<constructor-arg name="uname" value="张无忌"/>
<constructor-arg name="gender" value="男"/>
<constructor-arg name="age" value="22"/>
</bean>
- name:指定构造方法中的参数名称。
- index:指明该参数对应着构造器的第几个参数,从0开始,该属性不要也可,但要注意赋值顺序要与构造器中的参数顺序一致。
- 如果使用index属性,则用以下代码所示进行注入。
<bean id="user4" class="com.lifeng.entity.User">
<constructor-arg index="0" value="4"/>
<constructor-arg index="1" value="张无忌"/>
<constructor-arg index="2" value="男"/>
<constructor-arg index="3" value="22"/>
</bean>
4.2 p命名空间注入
- 使用p命名空间将可以简化属性值的注入。
(1)首先需要在项目spring4的spring配置文件头中引入p命名空间。
xmlns:p=“http://www.springframework.org/schema/p”
(2)在spring配置文件中再添加一个bean,使用p命名空间注入属性值。
<bean id="user5" class="com.lifeng.entity.User"
p:uid="5" p:uname="王五" p:gender="女" p:age="23"/>
- p 命名空间注入:也是采用设值注入方式,故需要有相应属性的 setter方法,通过上面代码可知,对照普通的设值注入,p命名空间注入简化很多。其基本语法参见表
4.3 各种数据类型的注入
1.注入常量
使用子节点,将常量(字符串及基本数据类型)值于中间,如5.4.1的设值注入第二种格式所示。也可以不用子节点,而是直接在节点中嵌入value属性,如5.4.1的设值注入第一种格式所示。
注入字符串常量值如果用到以下特殊字符,则需要替换为表5.2对应的表达式。
2.引用其他Bean组件
Spring中定义的各个bean之间可以互相引用(注入),借于建立依赖关系,可以使用ref属性实现,也可于用子节点实现。
项目案例:新建一个Company类,定义公司的编号,名称,地址属性,修改用户User类,添加一个Company类型的属性,用于设置用户所在的公司。(项目源码见本书配套源码: 第5章/基于xml的依赖注入/spring4)
-
(1)创建两个类 user +Company
-
(2) 引入bean 组件
-
(3)在user类中引入Company 的bean
<bean id="myCompany" class="cn.entity.Company">
< property name=id>
<value>1</value>
</property >
< property name=company>
<value>合肥</value>
</property >
</bean>
<bean id="user" class="cn.entity.user">
< property name=id>
<value>1</value>
</property >
< property name=user>
<value>广州</value>
</property >
< property name="company">
<ref bean="mycompany">
</property >
</bean>
4.4 自动注入
对于属性的注入,可不在配置文件中注入,通过标签 设置属性autowire属性值,从而为域属性进行隐式自动注入《自动装配》,可分为两种。
byname 名称自动注入
byType 类型自动注入
- 当配置文件中被调用者Bean的id值与代码中调用者Bean类的属性名相同时,可使用byName方式,让容器自动将被调用者Bean注入给调用者Bean。容器通过调用者的Bean类的属性名与配置文件的被调用者Bean的id进行比较而实现自动注入。
项目案例:先创建一个Company类的bean,其id为company,再创建一个User类型的bean,其id为user7, user7这个bean中company属性的注入不再直接引用company,而是改为自动装配。
(1)在项目spring4的spring配置文件中创建Company类的bean,其id为company。
<bean id="company" class="com.lifeng.entity.Company">
<property name="id">
<value>2</value>
</property>
<property name="companyname">
<value>砺锋软件公司</value>
</property>
<property name="address">
<value>广州天河建中路</value>
</property>
</bean>
(2)创建一个User类型的bean,采用自动装配。
<bean id="user7" class="com.lifeng.entity.User" autowire="byName">
<property name="uid">
<value>7</value>
</property> <property name="uname">
<value>李四</value>
</property>
<property name="gender">
<value>女</value>
</property> <property name="age">
<value>19</value>
</property>
</bean>
2 .byType注入是指按类型进行匹配注入,即只要spring容器中有跟域属性类型相同的bean就自动注入,而跟名称无关。使用byType方式自动注入,要满足下面这个条件:配置文件中被调用者bean的class 属性指定的类,要与代码中调用者Bean类的某域属性类型同源,要么相同,要么有 is-a 关系(子类,或是实现类)。但这样的同源的被调用 bean 只能有一个。多于一个,容器就不知该匹配哪一个,从而导致报错。
(1)项目spring4中新建一个bean,id为user8,把装配方式改为byType,其他基本跟user7一样。
<bean id="user8" class="com.lifeng.entity.User" autowire="byType">
<-- 省略其他 -->
</bean>