首先来看看百度对IOC的定义:
控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。
Spring中用到的应该是依赖注入,即DI。
一、Spring的IOC(XML)
1. Spring的IOC
就是把我要用这个类,但是却把创建这个类的控制权交给别人,作用就是解耦。
2. Spring的容器
在获取Spring容器时有两种规则
- BeanFactory:延迟加载,什么时候用,什么时候加载
- ApplicationContext:立即加载
ClassPathXmlApplicationContext 只能加载类路径下的配置文件
FileSystemXmlApplicationContext 能加载磁盘任意位置的配置文件
3. Bean的实例化方式
- 调用默认无参构造函数:默认情况下,如果类中没有默认无参构造函数,则会失败。此种方法最多
- 使用静态工厂中的方法创建对象:需要使用bean标签的factory-method属性,指定静态工厂类中的方法
- 使用实例工厂中的方法创建对象:需要先创建实例工厂bean对象,然后使用bean标签的factory-bean指定实例工厂,factory-method指定工厂方法
4. Bean的使用范围
它是可以通过配置的方式来调整作用范围
配置的属性:bean标签的scope属性
属性取值:
singleton:单例
prototype:原型
request:作用范围是一次请求,和当前请求的转发
session:作用范围是一次会话
globalsession:作用范围是一次全局会话,集群中使用。用户和集群建立连接,不论是与那个服务器通信,都只建立一个对象。
5. Bean的生命周期
涉及两个属性,init-method,destroy-method
- 单例:
- 出生:容器创建时,则创建对象
- 活着:只要容器在,对象就一直存在
- 死亡:容器销毁,对象消亡
- 多例:
- 出生:容器创建时并不会实例化对象,每次使用时创建对象
- 活着:该对象存在引用,就会一直存在
- 死亡:该对象没有被引用,且长时间没有使用,则由垃圾回收器自动回收
6. Spring的依赖注入
注入的方式:
- 使用构造函数注入
- 标签:constructor-arg
- 标签属性:
- type:指定参数的类型
- index:指定参数的索引位置,从0开始
- name:指定参数的名称,一般用这一项
上面三个属性指定需要赋值的参数,下面两个属性指定赋什么值 - value:指定基本数据类型或String类型的数据
- ref:指定其他bean类型的数据
- 标签出现的位置:写在bean标签内部
- 使用set方法注入
- 标签:property
- 标签属性:
- name:指定参数的set方法名称,例如setDate用date表示,一般用这一项
- value:指定基本数据类型或String类型的数据
- ref:指定其他bean类型的数据
- 标签出现的位置:写在bean标签内部
- 使用注解注入
- 注入的类型:
- 基本类型和String类型
- 其它bean类型
- 复杂类型(集合类型)
-结构相同,标签可以互换。array,list,set相同,map,properties相同
- 注入的类型:
二、Spring的IOC(注解)**
1. 用于创建bean对象
相当于
<bean id=" " class=" "></bean>
@Component
- 作用:相当于配置了一个bean标签
- 出现位置:Class, interface (including annotation type), or enum declaration
- 属性:value。含义是指定bean的id,其id默认为当前类的短名首字母改小写
由此注解衍生的三个注解,它们和@Component的作用及属性一模一样:
- @Controller 一般用于表现层
- @Service 一般用于业务层
- @Repository 一般用于持久层
为了创建bean对象,需要在xml中告知spring在创建容器时需要扫描的包。当配置了此标签之后,spring容器就会去指定的包及其子包下寻找对应的注解。此标签是在context的名称空间里,所以必须先导入context名称空间。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan
base-package="com.walter"></context:component-scan>
</beans>
2. 用于注入数据
相当于
<property name=" " ref=" ">
<property name=" " value=" ">
@Autowired
作用:自动按照类型注入,不关心类的id,只要有唯一的类型匹配就能注入成功。如果注入的bean在容器中类型不唯一时,它会把变量名称作为bean的id,在容器中查找,找到后也能注入成功,如果没有找到一致的bean的id,则报错。
当我们使用注解注入时,set方法就不是必须的了。
@Qualifier
作用:在自动按照类型注入的基础之上,再按照bean的id注入。它在给类成员注入数据时,不能独立使用。但是在给方法的形参注入数据时,可以独立使用。
属性:value用于指定bean的id
@Resource
作用:直接按照bean的id注入,可替代@Autowired和@Qualifier。
属性:name:用于指定bean的id
限制:需要导入javax.annotation.Resource,属于J2EE,用来减少对spring的耦合
<!-- https://mvnrepository.com/artifact/javax.annotation/javax.annotation-api -->
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
以上三个注解都是用于注入其它bean类型的,用于注入基本类型和String类型需要使用
@Value
作用:用于注入基本类型和String类型。它可以借助spring的el表达式读取properties文件中的配置,见注解@PropertSource
属性:value用于指定需要注入的数据
3. 用于改变作用范围
相当于
<bean id=" " class=" " scope=" "></bean>
@Scope
作用:用于改变bean的作用范围
属性:value用于指定范围的取值,取值与xml中scope属性的取值相同,即singleton,prototype,request,session,globalsession。
4. 和生命周期相关
相当于
<bean id=" " class=" " init-method=" " destroy-method=" "></bean>
@PostContruct
作用:用于指定初始化方法
@PreDestroy
作用:用于指定销毁方法
5. Spring的新注解
新建一个java配置文件,相当于xml配置文件
@ComponentScan
作用:指定Component扫描的基础包,配合之前四类注解,即可自动创建bean对象。
属性:value用来指定基础包
@Configuration
作用:把当前类看成是spring的配置类
示例:
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml",AppConfiguration.class);
则该配置xml文件的位置将是和AppConfiguration.java在同一路径下。
@Bean
作用:把方法的返回值存入Spring容器中
属性:name:指定bean的id,默认值为方法的名称。
@Import
作用:导入其它配置类,并不会成为bean对象,无需使用该类中的方法,则使用该注解。
@PropertySource
需要PropertySource解释器,但从spring 4.3 verision开始就自带解释器了
示例:
@PropertySource(value={“classpath:config/app.properties”})
@Value(${server.port})
6. 与Junit整合
- 第一步:引入spring-test依赖包
- 第二步:使用junit提供的注解,把原有的main函数(junit隐含的main函数)替换掉,换成spring提供的。
@RunWith(SpringJUnit4ClassRunner.class) - 第三步:使用spring提供的注解告知spring需要的xml配置文件或者Java配置类所在的位置
@ContextConfiguration(locations={“classpath:bean.xml”})
@ContextConfiguration(classes={AppConfig.class}) - 第四步:自动注入测试方法中使用的类对象。
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.walter.config.ApplicationConfiguration;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes={ApplicationConfiguration.class})
public class CustomServiceTest
{
@Autowired
private ICustomerService customerService1;
@Test
public void testaddCustomer()
{
customerService1.addCustomer();
}
}