二 、 Spring 之 IOC 详解
(一)spring ioc 简介
IOC(控制反转:Inverse of Control ),是一种重要的面向对象编程的法则来削减计算机程序的耦合问题,也是轻量级的 Spring 框架的核心。
由原程序控制的对象的创建管理现在交由spring ioc容器来进行管理,这个过程就叫控制反转IOC
(二)spring ioc 原理
spring降低了耦合度,HelloWorld类名的修改不影响Test类的调用
http://editorxml.sourceforge.net/download.html
(三)spring ioc管理bean实例
1.装配一个 bean
![在这里插入图片描述](https://img-blog.csdnimg.cn/9946d0ee6549428bb9d3f400b2386152.png)2. bean的生命周期
bean的创建
单例模式:
(1)默认情况下,bean的创建是在new ClassPathXmlApplicationContext(“applicationContext.xml”)执行后被创建的
(2)假如使用lazy-init=“true” 单例模式使用懒加载机制,只有在使用的时候该bean才被实例化创建
多例模式:bean的创建是在使用ac.getBean(“student”)之后创建
bean的初始化
设定init-method=“init”,指定对象初始化的时候调用init(),初始化发生在对象创建后就会被初始化
bean的使用
调用该bean的具体方法 hw.sayHello()
bean的销毁
设定destroy-method=“destroy”,在销毁该bean时调用destroy()
单例模式
bean的销毁是随着spring ioc容器的关闭而销毁,会调用指定destroy()
@Test
public void test() {
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
HelloWorld hw1 = (HelloWorld) ac.getBean("helloWorld");
//关闭ioc容器
ac.close();
}
多例模式
bean的销毁是不归ioc容器管理的,交由jvm的gc进行管理
3.bean 作用范围 scope=""
singleton
单例模式 Spring ioc 容器中仅有一个 Bean 实例,Bean 以单例的方式存在;默认的范围prototype
原型模式(多例模式) 每次从容器中调用 Bean 时,都返回一个新的实例;- request 每次 HTTP请求都会创建一个新的 Bean;
- session 同一个 HTTP Session 共享一个 Bean;
- global session同一个全局 Session 共享一个 Bean,一般用于 Portlet 应用环境;
- application 同一个Application 共享一个 Bean;
单例模式和多例模式的区别:
(1)单例模式只会创建一个对象共用,多例模式每次通过getBean()获取的都是一个新的对象
(2)单例创建对象是在new ClassPathXmlApplicationContext(“applicationContext.xml”)后,而多例模式是在使用getBean()才创建出来,而且每调用一次getBean()都会创建一个新的对象出来
(四)spring ioc之依赖注入DI
依赖注入:给bean的属性赋值的方式
1.依赖注入方式
- 属性注入,setter注入,要求对应属性一定要提供对应的set方法
<bean id="student" class="org.lanqiao.service.Student">
<property name="sid" value="1"></property>
<property name="sname" value="张三"></property>
<property name="sage" value="21"></property>
</bean>
- 构造函数注入;(通过名称name,通过类型type;通过索引index;联合使用)
<bean id="student2" class="org.lanqiao.service.Student">
<constructor-arg name="sid" value="2"></constructor-arg>
<constructor-arg name="sage" value="23"></constructor-arg>
<constructor-arg name="sname" value="李四"></constructor-arg>
</bean>
必须要提供对应的构造方法
- 工厂方法注入;(非静态工厂,静态工厂)
<!-- 使用非静态工厂注入 -->
<bean id="studentFactory" class="org.lanqiao.service.StudentFactory"/>
<bean id="student3" factory-bean="studentFactory" factory-method="createStudent2"/>
<!-- 使用静态工厂注入 -->
<bean id="student4" class="org.lanqiao.service.StudentFactory2" factorymethod="createStudent2"/>
p命名空间注入
spEL注入 #{}
2.依赖注入参数各种类型
- 基本类型值
- 注入 bean 引用方式注入bean
<bean id="grade" class="org.lanqiao.entity.Grade">
<property name="gid" value="3"></property>
<property name="gname" value="大3"></property>
</bean>
<bean id="student1" class="org.lanqiao.entity.Student">
<property name="sid" value="1"></property>
<property name="sname" value="小1"></property>
<property name="sage" value="11"></property>
<property name="grade" ref="grade"></property>
</bean>
- 内部 bean
<bean id="student2" class="org.lanqiao.entity.Student">
<property name="sid" value="2"></property>
<property name="sname" value="小2"></property>
<property name="sage" value="22"></property>
<property name="grade">
<bean class="org.lanqiao.entity.Grade">
<property name="gid" value="2"></property>
<property name="gname" value="大2"></property>
</bean>
</property>
</bean>
- null 值
<bean id="student3" class="org.lanqiao.entity.Student">
<property name="sid" value="3"></property>
<property name="sname" value="小3"></property>
<property name="sage" value="33"></property>
<property name="grade">
<null></null>
</property>
</bean>
- 级联属性
<!-- 使用级联属性赋值 ,注:需要Grade首先被实例化才可以使用该方式-->
<bean id="student4" class="org.lanqiao.entity.Student">
<property name="sid" value="4"></property>
<property name="sname" value="小4"></property>
<property name="sage" value="44"></property>
<property name="grade.gid" value="4"></property>
<property name="grade.gname" value="大4"></property>
</bean>
- 集合类型属性
<!-- list集合注入 -->
<bean id="student5" class="org.lanqiao.entity.Student">
<property name="sid" value="5"></property>
<property name="sname" value="小5"></property>
<property name="sage" value="55"></property>
<property name="grade" ref="grade"></property>
<property name="hoobies">
<list>
<value>唱歌</value>
<value>跳舞</value>
<value>踢足球</value>
</list>
</property>
</bean>
<!-- set集合注入 -->
<bean id="student6" class="org.lanqiao.entity.Student">
<property name="sid" value="6"></property>
<property name="sname" value="小6"></property>
<property name="sage" value="66"></property>
<property name="grade" ref="grade"></property>
<!--Set<String> hoobies2;-->
<property name="hoobies2">
<set>
<value>唱歌</value>
<value>唱歌</value>
<value>跳舞</value>
<value>踢足球</value>
</set>
</property>
</bean>
<!-- map集合注入 -->
<bean id="student7" class="org.lanqiao.entity.Student">
<property name="sid" value="7"></property>
<property name="sname" value="小7"></property>
<property name="sage" value="77"></property>
<property name="grade" ref="grade"></property>
<property name="hoobies3">
<map>
<entry>
<key><value>1</value></key>
<value>语文</value>
</entry>
<entry>
<key><value>2</value></key>
<value>数学</value>
</entry>
</map>
</property>
</bean>
<!-- properties集合注入 -->
<bean id="student8" class="org.lanqiao.entity.Student">
<property name="sid" value="8"></property>
<property name="sname" value="小8"></property>
<property name="sage" value="88"></property>
<property name="grade" ref="grade"></property>
<property name="prop">
<props>
<prop key="driver">com.mysql.jdbc.Driver</prop>
<prop key="name">root</prop>
<prop key="psw">123</prop>
</props>
</property>
</bean>
3.Spring 自动装配
通过配置 default-autowire 属性,Spring IOC 容器可以自动为程序注入 bean;默认是 no,不启用自动装配;
default-autowire 的类型有 byName,byType,constructor;
byName:通过名称进行自动匹配; @Resource
byType:根据类型进行自动匹配; @Autowired
constructor:和 byName类似,只不过它是根据构造方法注入而言的,根据类型,自动注入;
建议:自动装配机制慎用,它屏蔽了装配细节,容易产生潜在的错误;
4.bean 之间的关系
- 继承
<bean id="studentParent" class="org.lanqiao.entity.Student">
<property name="sage" value="22"></property>
</bean>
<bean id="student1" parent="studentParent">
<property name="sid" value="1"></property>
<property name="sname" value="张三"></property>
</bean>
<bean id="student2" parent="studentParent">
<property name="sid" value="2"></property>
<property name="sname" value="张三2"></property>
</bean>
- 依赖
注:springIOC容器一次性的创建所有定义的bean,初始化是按照配置文件当中的顺序进行实例化bean
一个bean A依赖于另外一个bean B,不管定义顺序,首先要保证先创建B,再创建A
<bean id="student3" parent="studentParent" depends-on="studentLog">
<property name="sid" value="2"></property>
<property name="sname" value="李四"></property>
<property name="sage" value="21"></property>
</bean>
<bean id="studentLog" class="org.lanqiao.log.StudentLog"></bean>
- 引用
<bean id="student3" parent="studentParent" depends-on="studentLog">
<property name="sid" value="2"></property>
<property name="sname" value="李四"></property>
<property name="sage" value="21"></property>
<property name="grade" ref="grade"></property>
</bean>
<bean id="studentLog" class="org.lanqiao.log.StudentLog"></bean>
<bean id="grade" class="org.lanqiao.entity.Grade"></bean>
5.方法注入 lookup-method
单例模式去引用多例模式的时候,多例返回的仍然是同一个对象
6.方法的替换 replaced-method