JavaWeb——Spring 系列
二、Spring IoC
- 在上一篇介绍了 Spring 的基本组成,这一篇将记录我对 Spring 的 IoC 的学习。
- 所谓 IoC,就是控制反转(Inversion of Control),使程序组件或类之间尽可能形成一种松耦合的结构,在传统 Java 编程中,如果要使用一个类,就必须先创建类的对象实例;而在 Spring 编程中,这一步不在由开发者编写,而是交由 IoC 容器进行对象实例化;实现这个过程的操作,称之为依赖注入(Dependency Injection)
1、依赖注入
- 依赖注入有三种实现方式:接口注入、Setter 注入和构造器注入。
- 所谓接口注入,是指基于接口将调用与实现分离。
- Setter 注入,基于 JavaBean 的 Setter 方法为属性赋值,实际开发中广泛使用。
- 构造器注入就是利用类的构造方法为属性赋值。
- Spring 支持后两者。
1.1、Setter 注入示例
- 见上一篇中的 Spring 简单示例
1.2、构造器示例
- 首先建一个 Java 类,代码如下:
//IntelliJ IDEA //Sprin01 //Agent //2020/1/11 // Author:御承扬 //E-mail:2923616405@qq.com package com.myCode.beanSet; public class Agent { private String name; private Integer age; private String sex; private String addr; public Agent(String name,Integer age, String sex, String addr){ this.name=name; this.age=age; this.sex=sex; this.addr=addr; } public void printInfo(){ System.out.println("客户姓名:"+name); System.out.println("客户年龄:"+age); System.out.println("客户性别:"+sex); System.out.println("客户地址:"+addr); } }
- 在 applicationContext.xml 文件中增加以下代码:
<bean name="agent" class="com.myCode.beanSet.Agent"> <constructor-arg value="时风"/> <constructor-arg value="26"/> <constructor-arg value="男"/> <constructor-arg value="史兰县"/> </bean>
- 在 Manager.java 中增加如下代码:
Agent agent = (Agent)factory.getBean("agent"); agent.printInfo();
- 输出如下:
客户姓名:时风 客户年龄:26 客户性别:男 客户地址:史兰县
2、Bean 的自动装配
- Spring 的配置文件 applicationContext.xml 的<bean>标签的 autowire 属性,支持对指定的 JavaBean 的相关属性进行自动装配。
2.1、自动装配的优缺点
- 通过使用自动装配可以节省许多 JavaBean 属性的标签代码,从而使得代码更为整洁,这个就是自动装配的优点。
- 自动装配的缺点在于,使用了自动装配方式后,很难通过阅读配置文件了解 JavaBean 需要什么属性。
2.2、自动装配的分类
- 按照自动装配的实现机制,可以分为:按 bean 名称装配、按 bean 类型装配。
2.2、自动装配示例
- 这里贴出按 bean 名称装配的示例,因为按 bean 类型装配的只需要将 autowire 的属性值设置为 byType 即可。
- 示例代码如下:
- 首先新建一个 PrintAgentInfo 类,代码如下:
//IntelliJ IDEA //Sprin01 //PrintAgentInfo //2020/1/12 // Author:御承扬 //E-mail:2923616405@qq.com package com.myCode.beanSet; public class PrintAgentInfo { private Agent agent; public Agent getAgent() { return agent; } public void setAgent(Agent agent) { this.agent = agent; } public void PrintAgent(){ System.out.println("PrintAgentInfo 打印的 Agent 属性"); System.out.println("客户姓名:"+agent.getName()); System.out.println("客户年龄:"+agent.getAge()); System.out.println("客户性别:"+agent.getSex()); System.out.println("客户地址:"+agent.getAddr()); } }
- 接着对 Agent 类进行适当修改,增加属性的 set 方法和 get 方法,如下:
public void setName(String name) { this.name = name; } public void setSex(String sex) { this.sex = sex; } public void setAge(Integer age) { this.age = age; } public void setAddr(String addr) { this.addr = addr; } public String getName() { return name; } public String getSex() { return sex; } public Integer getAge() { return age; } public String getAddr() { return addr; }
- 在 applicationContext.xml 文件中增加如下一句话:
<bean autowire="byName" id="printAgentInfo" class="com.myCode.beanSet.PrintAgentInfo"/>
- 在 Manager 中对 PrintAgentInfo 进行使用:
PrintAgentInfo printAgentInfo = (PrintAgentInfo)factory.getBean("printAgentInfo"); printAgentInfo.PrintAgent();
- 效果如下:
PrintAgentInfo 打印的 Agent 属性 客户姓名:时风 客户年龄:26 客户性别:男 客户地址:史兰县
3、Spring 中 Bean 的作用域
- bean 在 Spring 编程中,可以理解为一种由 Spring 容器初始化、装配和管理的对象。
- 在 Spring 中 bean 由配置文件(XML 文件)的 <bean> 标签来声明,该元素通过属性 scope 来确定 bean 的作用,scope 可选值为:singleton 和 prototype。
3.1、singleton
- 当 bean 的作用域为 singleton 时,Spring IoC 容器中只会存在一个共享的该 bean 实例,并且所有对该 bean 的引用,若 id 和 name 匹配就返回 bean 的单一实例;此时,bean 的生命周期和 Spring IoC 容器的是一致的;bean 默认作用域为 singleton
- 示例:
<bean id="demo" class="Demo"/> <bean id="demo" class="Demo" singleton="true"/> <bean id="demo" class="Demo" scope="singleton"/>
3.2、prototype
- prototype 作用域的 bean 会在每次请求时创建一个新的 bean 实例返回给请求方,并将该实例的生命周期交给请求方管理,因此需要使用 bean 的后置处理器清除 prototype 作用域的 bean(后置处理器需持有要被清除的 bean 的引用)。
- 鉴于 prototype 作用域的特性,所有有状态的 bean 应当使用 prototype作用域,无状态的则使用 singleton 作用域。
- 示例
<bean id="demo" class="Demo" singleton="false"/> <bean id="demo" class="Demo" scope="prototype"/>