Spring IOC 控制反转
什么是控制反转
IOC(Inverse Of Control)控制反转,即,把创建对象的权利交给框架。
也就是指将对象的创建、对象的存储、对象的管理交给了spring容器。
(spring容器是spring中的一个核心模块,用于管理对象,底层可以理解为是一个map集合)
具体实现
在此之前,当需要对象时,通常是利用new关键字创建一个对象:
但由于new对象,会提高类和类之间的依赖关系,即代码之间的耦合性。
而现在我们可以将对象的创建交给框架来做:
只需要将类提前配置在配置文件中,就可以将对象的创建交给框架来做。当需要对象时,不需要自己创建,而是通过框架直接获取即可,省去了new对象的过程,自然就降低类和类之间的依赖关系,也就是耦合性。
Spring 容器高层视图
Spring 启动时读取应用程序提供的Bean 配置信息,并在Spring 容器中生成一份相应的Bean 配
置注册表,然后根据这张注册表实例化Bean,装配好Bean 之间的依赖关系,为上层应用提供准
备就绪的运行环境。其中Bean 缓存池为HashMap 实现
**Map<String,BeanDefiniton>**对象的定义信息
Map<String,object> 管理对象
IOC入门案例
下面将使用spring的IOC解决程序间的耦合
1.创建spring配置文件
创建spring核心配置文件—applicationContext.xml
1、在工程的src/main/resources源码目录下,创建applicationContext.xml文件:
2、在applicationContext.xml中添加文件头信息:
3、将EmpService接口的实现类的实例
以及EmpDao接口的实现类的实例交给Spring容器创建,在核心配置文件中添加如下配置:
2.创建测试类进行解耦
创建测试类—TestSpring,通过spring的IOC解决程序中的耦合问题
1、创建测试类
2、测试步骤及代码如下:
3、运行结果
4、入门案例总结:
这就是spring框架的IOC——控制反转。之前我们自己new对象,例如:
而现在,变成由一个初始化的xml配置文件来创建,也就是由spring容器来创建。
当程序运行,spring开始工作后,会加载整个xml核心配置文件,读取到,获取到class属性中类的全路径,利用反射创建该类的对象。
Spring框架管理Bean对象的优势
Spring 是一个资源整合框架(Framework),通过spring可将很多资源(自己写的对象或第三方提供的对象,例如连接池等)整合在一起,然后进行科学应用,以便更好的对外提供服务。
懒加载策略 @Lazy(true) 默认为true
作用域 @Scope(“singleton”) 默认单例
生命周期方法 lifecycle method @PostConstruct @PreDestroy
Spring框架可以为由它管理的对象(Bean)提供懒加载策略(对象暂时用不到,则无需加载和实例化),作用域(例如singleton-频繁用时可以考虑内存中只有一份,prototype-使用次数少时可以用时创建,不用时销毁),生命周期方法(更好实现对象的初始化和资源销毁),以实现对象对系统资源的有效使用。同时Spring框架还可以基于用户设计管理对象与对象的依赖关系,以降低对象与对象之间的直接耦合,提高程序的可维护性和可扩展性。
懒加载(Lazy)
在Spring框架中,默认会在启动时会创建所有的Bean对象,但有些bean对象假如长时间不用,启动时就创建对象,会占用其内存资源,从而造成一定的资源浪费,此时我们可以基于懒加载策略延迟对象的创建,在设计类时,在类上添加@Lazy注解,
@Lazy(true)//此注解用于告诉spring框架,它描述的类的实例,假如暂时用不到,就不要先创建
spring中 @Lazy注解中有一个value属性,其默认值为true表示延迟加载
Spring Bean 作用域(Scope)
Spring框架创建对象以后,可以给对象一个作用域,目的是让对象在一定范围内可以进行重用,默认是单例模式singleton
Spring 3 中为Bean 定义了5 中作用域,分别为singleton(单例)、prototype(原型)、
request、session 和global session,5 种作用域说明如下:
singleton 单例模式(多线程不安全)
- singleton:单例模式,Spring IoC 容器中只会存在一个共享的Bean 实例,无论有多少个
Bean 引用它,始终指向同一对象。该模式在多线程下是不安全的。Singleton 作用域是
Spring 中的缺省作用域,也可以显示的将Bean 定义为singleton 模式,配置为:
prototype:多例模式(原型模式)每次使用时被创建
- prototype:原型模式,每次通过Spring 容器获取prototype 定义的bean 时,容器都将创建
一个新的Bean 实例,每个Bean 实例都有自己的属性和状态,而singleton 全局只有一个对象。根据经验,对有状态的bean使用prototype作用域,而对无状态的bean使用singleton作用域。
Request:一次request一次实例
- request:在一次Http 请求中,容器会返回该Bean 的同一实例。而对不同的Http 请求则会
产生新的Bean,而且该bean 仅在当前Http Request 内有效,当前Http 请求结束,该bean
实例也将会被销毁。
session
- session:在一次Http Session 中,容器会返回该Bean 的同一实例。而对不同的Session 请求则会创建新的实例,该bean 实例仅在当前Session 内有效。同Http 请求相同,每一次session 请求创建新的实例,而不同的实例之间不共享属性,且实例仅在自己的session 请求内有效,请求结束,则实例将被销毁。
global Session
- global Session:在一个全局的Http Session 中,容器会返回该Bean 的同一个实例,仅在
使用portlet context 时有效。
生命周期方法
程序中每个对象都有生命周期,但不是每个对象类型定义时,都要定义生命周期方法,当一个Bean对象创建以后假如还需执行额外初始化,销毁之前也需要额外的其它资源的释放,Spring框架可以为类定义其生命周期方法。
bean 标签有两个重要的属性(init-method 和destroy-method)。用它们你可以自己定制
初始化和注销方法。它们也有相应的注解(@PostConstruct 和@PreDestroy)。
- @PostConstruct 注解描述的方法会在对象构建以后执行,用于执行一些初始化操作
- @PreDestroy 注解描述的方法会在单例对象销毁之前执行,spring容器在销毁之前会先将容器(Bean池)中的对象进行移除,在移除对象时,假如对象中定义了生命周期销毁方法,此时还会调用对象的生命周期销毁方法(在这样的方法中可以做一些资源释放操作)。
另:@Scope(“prototype”)创造出来的bean对象不会存在bean池中,所以得手动销毁
一般池对象都会设置一些生命周期方法,例如连接池。
什么是bean?
在Spring框架中由Spring创建和管理的对象的对象称之为Bean对象。
我们在java中,会把满足一定规范的java对象叫做bean对象。规范如下:
(1)必须是public的类
(2)必须具备无参数构造方法
(3)有公开的get set方法
(4)必须是可序列化(在序列化方式改进之后,这个规范不是必须的)
Serializable
:可序列化接口,是一个标识接口。
序列化的概念:把java对象拆分成一个一个的字节单元,便于存储到磁盘或者用于网络传输。
反序列化:就是把一个一个的字节单元读取回来,组成一个java对象。
在早期,Java要想实现序列化,只能通过java原生的序列化方式,也就是通过实现序列化接口来实现序列化。但是后来随着java的发展,衍生很多的第三方序列化jar包。
他们的序列化性能比原生的更好,而且不需要实现序列化也可以序列化。
Spring DI依赖注入
DI(Dependency Injection)依赖注入 。
依赖注入,即组件之间的依赖关系由容器在应用系统运行期来决定,也就是由容器动态地将某种依赖关系的目标对象实例注入到应用系统中的各个关联的组件之中。
简单来说,所谓的依赖注入其实就是,在创建对象的同时或之后,如何给对象的属性赋值。
spring有4种依赖注入方式:
Set方法注入
构造器注入
静态工厂的方法注入
实例工厂的方法注入
按照实现方式分为两类:
注解(如@Autowired)
配置文件(如xml)
1、Set方法注入
2、构造方法注入
构造方法注入是指带有参数的构造函数注入
注解方式
xml方式
其中,constructor-arg标签name属性的值必须和构造函数中参数的名字相同!
同样的,普通属性直接通过value注入即可;
对象属性通过ref属性注入。
3、静态工厂的方法注入
静态工厂顾名思义,就是通过调用静态工厂的方法来获取自己需要的对象。
为了使用Spring的依赖注入IOC,我们不直接通过"工程类.静态方法()"来获取对象,而是依然通过spring注入的形式获取:
此种方式无通过注解注入
4、实例工厂的方法注入
实例工厂的意思是获取对象实例的方法不是静态的,所以你需要首先new工厂类,再调用普通的实例方法:
此种方式无通过注解注入