文章目录
一、IOC的概念和作用1基本概念
二、使用spring框架来实现前文的解耦案例1.项目环境搭建2.ApplicationContext的3个常用实现类3.核心容器的两个接口引发的问题3.1`ApplicationContext`3.2`BeanFactory`3.3使用选择
三、spring对bean的管理细节1.创建bean的三种方式1.1方式一:使用默认构造函数1.2方式二:使用实例工厂的方法创建对象1.3方式三:使用静态工厂的静态方法来创建对象
2.bean的作用范围2.1默认作用范围( singleton:单例的)2.2设置多例的作用范围( prototype)2.3小结2.4global-session简单了解
3.bean对象的生命周期3.1单例对象的生命周期3.2多例对象的生命周期
四、spring的依赖注入1.基本概念2注入数据类型和方式2.1三类数据2.2三种注入方式
3第一种注入方式:使用构造函数提供3.1bean类提供带参的构造函数3.2配置方法3.2.1配置实例
3.3运行效果3.4优势和弊端
4第二种注入方式:使用set方法提供(更常用)4.1bean类提供属性的set方法4.2配置方法4.2.1配置实例
4.3运行效果4.4优势和弊端
5.复杂数据类型(集合类型)的注入案例5.1含有复杂数据类型的bean类5.2配置方法5.2.1标签小结
5.3运行效果
一、IOC的概念和作用
1基本概念
这里我们先简单总结下前文中创建对象的两种方式
前文中两种不同的方式来创建对象就是一个典型的对比 - 前一种获取对象的方式是主动的,直接new,将应用和资源直接绑定在一起 - 后一种方式,把创建对象交给工厂,我们只需要和工厂打交道即可 - 由工厂来控制资源和提供资源,减少程序间的耦合性
二、使用spring框架来实现前文的解耦案例
1.项目环境搭建
创建maven项目复制上文的主要代码设置pom.xml文件,导入spring的jar包坐标
<dependencies>
<dependency>
<groupId>org.springframework
</groupId>
<artifactId>spring-context
</artifactId>
<version>5.0.2.RELEASE
</version>
</dependency>
</dependencies>
导入后,可以发现相关jar包的信息 新建资源文件bean.xml导入约束 接下来把对象的创建交给spring来管理,在配置文件中进行配置
<bean id="accountService" class="com.xpt.service.impl.AccountServiceImpl"></bean>
<bean id="accountDao" class="com.xpt.dao.impl.AccountDaoImpl"></bean>
创建对象,分为如下两步
获取core对象根据配置文件中的id获取对象
public class Client {
public static void main(String
[] args
) {
ApplicationContext ac
= new ClassPathXmlApplicationContext("bean.xml");
IAccountService as
= (IAccountService
) ac
.getBean("accountService");
IAccountDao dao
= (IAccountDao
) ac
.getBean("accountDao");
System
.out
.println(as
);
System
.out
.println(dao
);
}
}
- 可以看到上述的过程代码非常的少,从配置文件解析到对象创建全都由spring做了
2.ApplicationContext的3个常用实现类
ClassPathXmlApplicationContext:加载类路径下的配置文件,要求配置文件必须在类路径下,不在的话,加载不了。(相较于下一种更推荐使用)FileSystemXmlApplicationContext:可以加载磁盘任意路径下的配置文件,但必须有访问权限AnnotationConfigApplicationContext:它是用于读取注解创建容器的。
3.核心容器的两个接口引发的问题
3.1ApplicationContext
它在创建核心容器时,对象创建的策略是采用立即加载的方式,也就是说,只要一读取完配置文件就能马上创建配置文件种配置好的对象。
验证:在bean类中定义一个空参的构造函数
public class AccountServiceImpl implements IAccountService {
IAccountDao accountDao
= new AccountDaoImpl();
public AccountServiceImpl(){
System
.out
.println("对象已经被创建了");
}
public void saveAccount() {
accountDao
.saveAccount();
}
}
Client类中注释掉后面的对象获取
public class Client {
public static void main(String
[] args
) {
ApplicationContext ac
= new ClassPathXmlApplicationContext("bean.xml");
}
}
运行效果:
3.2BeanFactory
它在构建核心容器的时候,创建对象的策略是采用延迟加载的方式,也就是说,什么时候根据id获取对象了,什么时候才真正的创建对象。
演示:修改代码
Resource resource
= new ClassPathResource("bean.xml");
BeanFactory factory
= new XmlBeanFactory(resource
);
IAccountService as
= (IAccountService
) factory
.getBean("accountService");
System
.out
.println(as
);
断点调试 - 继续执行
3.3使用选择
上面演示了两种容器接口创建对象的不同时机,那在实际开发中如何选择呢?单例对象的情况下,对象只被创建一次,然后多次使用,这种时候肯定希望立即加载,所以ApplicationContext更适用于单例对象,那么显然BeanFactory更适用于多例对象使用
三、spring对bean的管理细节
1.创建bean的三种方式
1.1方式一:使用默认构造函数
在spring的配置文件中使用bean标签,配以id和class属性,且没有其他的属性和标签时。采用的就算默认构造函数创建bean对象,如果此时类中没有默认构造函数,则对象无法创建
演示效果配置文件
<bean id="accountService" class="com.xpt.service.impl.AccountServiceImpl"></bean>
设置bean类无默认构造函数
public class AccountServiceImpl implements IAccountService {
public AccountServiceImpl(String name
){
System
.out
.println("对象已经被创建了");
}
public void saveAccount() {
System
.out
.println("service中的saveAccount方法执行了");
}
}
测试类
public class Client {
public static void main(String
[] args
) {
ApplicationContext ac
= new ClassPathXmlApplicationContext("bean.xml");
IAccountService as
= (IAccountService
) ac
.getBean("accountService");
System
.out
.println(as
);
}
}
运行结果报错
1.2方式二:使用实例工厂的方法创建对象
使用普通工厂中的方法创建对象 或者使用某个类中的方法创建对象,并存入spring容器
演示配置
<bean id="instanceFactory" class="com.xpt.factory.InstanceFactory"></bean>
<bean id="accountService" factory-bean="instanceFactory" factory-method="getAccountService"></bean>
模拟实例工厂类
public class InstanceFactory {
public IAccountService
getAccountService(){
return new AccountServiceImpl();
}
}
其余部分代码不变,之间运行测试类,结果成功创建对象
1.3方式三:使用静态工厂的静态方法来创建对象
使用静态工厂的静态方法来创建对象 或者使用某个类的静态方法创建对象,并存入spring容器
演示配置
<bean id="accountService" class="com.xpt.factory.StaticFactory"
factory-method="getAccountService" ></bean>
静态工厂和静态方法
public class StaticFactory {
public static IAccountService
getAccountService(){
return new AccountServiceImpl();
}
}
其余代码不变,直接运行测试类,成功创建对象
2.bean的作用范围
2.1默认作用范围( singleton:单例的)
默认作用范围是单例的,即创建的bean都是一个对象
演示
2.2设置多例的作用范围( prototype)
xml配置 - 运行测试
2.3小结
bean标签的scope属性: 作用:用于指定bean的作用范围 取值: 常用的就是单例的和多例的
singleton:单例的(默认值)prototype:多例的request:作用于web应用的请求范围session:作用于web应用的会话范围global-session:作用于集群环境的会话范围(全局会话范围),当不是集群环境时,它就是session
2.4global-session简单了解
3.bean对象的生命周期
3.1单例对象的生命周期
出生:当容器创建时对象出生
活着:只要容器还在,对象一直活着
死亡:容器销毁,对象消亡
总结:单例对象的生命周期和容器相同
演示
xml配置
bean类中添加init和destroy方法
public void saveAccount() {
System
.out
.println("service中的saveAccount方法执行了");
}
public void init() {
System
.out
.println("对象创建");
}
public void destroy() {
System
.out
.println("对象销毁");
}
测试类改造: - 结果:
3.2多例对象的生命周期
出生:当我们使用对象时spring框架为我们创建(延迟加载,spring会智能的判断对象是单例还是多例的,然后智能选择加载方式,这里回想前面核心容器的两个不同的加载方式)活着:对象只要是在使用过程中就一直活着。死亡:当对象长时间不用,且没有别的对象引用时,由Java的垃圾回收器回收验证xml配置 - 其余部分不变,测试代码结果
四、spring的依赖注入
1.基本概念
依赖注入:Dependency InjectionIOC的作用: 降低程序间的耦合(依赖关系)依赖关系的管理:以后都交给spring来维护在当前类需要用到其他类的对象,由spring为我们提供,我们只需要在配置文件中说明,依赖关系的维护:就称之为依赖注入。
2注入数据类型和方式
2.1三类数据
基本类型和String其他bean类型(在配置文件中或者注解配置过的bean)复杂类型/集合类型
2.2三种注入方式
第一种:使用构造函数提供第二种:使用set方法提供第三种:使用注解提供
3第一种注入方式:使用构造函数提供
下面演示基于这种方式的配置过程
3.1bean类提供带参的构造函数
public class AccountServiceImpl implements IAccountService {
private String name
;
private Integer age
;
private Date birthday
;
public AccountServiceImpl(String name
, Integer age
, Date birthday
) {
this.name
= name
;
this.age
= age
;
this.birthday
= birthday
;
}
public void saveAccount() {
System
.out
.println("service中的saveAccount方法执行了:"+name
+","+age
+","+birthday
);
}
}
注意
现在上述的bean类中没有默认的构造函数,所以在配置的时候肯定无法使用默认的构造函数来创建bean对象 - 所以为了解决上面的问题就需要进行构造函数的依赖注入的配置
3.2配置方法
使用的标签:constructor-arg标签出现的位置:bean标签的内部标签中的属性
type:用于指定要注入的数据的数据类型,该数据类型也是构造函数中某个或某些参数的类型index:用于指定要注入的数据给构造函数中指定索引位置的参数赋值。索引的位置是从0开始name:用于指定给构造函数中指定名称的参数赋值(推荐) 以上三个用于指定给构造函数中哪个参数赋值
value:用于提供基本类型和String类型的数据ref:用于指定其他的bean类型数据。它指的就是在spring的Ioc核心容器中出现过的bean对象
3.2.1配置实例
3.3运行效果
代码
public class Client {
public static void main(String
[] args
) {
ApplicationContext ac
= new ClassPathXmlApplicationContext("bean.xml");
IAccountService as
= (IAccountService
) ac
.getBean("accountService");
System
.out
.println(as
);
as
.saveAccount();
}
}
结果 - 顺利执行
3.4优势和弊端
优势: 在获取bean对象时,注入数据是必须的操作,否则对象无法创建成功。弊端:改变了bean对象的实例化方式,使我们在创建对象时,如果用不到这些数据,也必须提供。
4第二种注入方式:使用set方法提供(更常用)
4.1bean类提供属性的set方法
只提供set方法即可
4.2配置方法
涉及的标签:property出现的位置:bean标签的内部标签的属性
name:用于指定注入变量的名称value:用于提供基本类型和String类型的数据ref:用于指定其他的bean类型数据。它指的就是在spring的Ioc核心容器中出现过的bean对象
4.2.1配置实例
4.3运行效果
代码同上
4.4优势和弊端
优势:创建对象时没有明确的限制,可以直接使用默认构造函数弊端: 如果有某个成员必须有值,则获取对象是有可能set方法没有执行。
5.复杂数据类型(集合类型)的注入案例
使用set方式注入复杂数据类型
5.1含有复杂数据类型的bean类
public class AccountServiceImpl3 implements IAccountService {
private String
[] myStrs
;
private List
<String> myList
;
private Set
<String> mySet
;
private Map
<String,String> myMap
;
private Properties myProps
;
public void setMyStrs(String
[] myStrs
) {
this.myStrs
= myStrs
;
}
public void setMyList(List
<String> myList
) {
this.myList
= myList
;
}
public void setMySet(Set
<String> mySet
) {
this.mySet
= mySet
;
}
public void setMyMap(Map
<String, String> myMap
) {
this.myMap
= myMap
;
}
public void setMyProps(Properties myProps
) {
this.myProps
= myProps
;
}
public void saveAccount(){
System
.out
.println(Arrays
.toString(myStrs
));
System
.out
.println(myList
);
System
.out
.println(mySet
);
System
.out
.println(myMap
);
System
.out
.println(myProps
);
}
5.2配置方法
配置实例
<bean id="accountService03" class="com.xpt.service.impl.AccountServiceImpl3">
<property name="myStrs">
<array>
<value>array
</value>
</array>
</property>
<property name="myList">
<list>
<value>list
</value>
</list>
</property>
<property name="mySet">
<set>
<value>set
</value>
</set>
</property>
<property name="myMap">
<map>
<entry key="mapA" value="valueA"></entry>
<entry key="mapB" value="valueB"></entry>
</map>
</property>
<property name="myProps">
<props>
<prop key="propA">valueA
</prop>
</props>
</property>
</bean>
5.2.1标签小结
用于给List结构集合注入的标签: list array set用于个Map结构集合注入的标签: map props结构相同,标签可以互换
5.3运行效果