Spring(二)spring核心技术——ioc
一、Spring核心技术——IOC
IOC是Inversion of Control的缩写,即控制反转;是一种思想、理论、概念。IOC把对象的创建、管理、属性的赋值,都交给代码之外的容器实现,通过外部资源完成。使用ICO的目的就是在减少对代码改动的情况下,实现不同的功能,实现解耦合。
-
控制:创建对象,对象的属性赋值,对象之间的关系管理。
-
反转:把原来的开发人员管理,创建对象的权限转移给代码之外的容器实现。由容器代替开发人员管理对象。创建对象,给属性赋值。
-
正转:由开发人员在代码中,使用new构造方法创建对象,开发人员主动管理对象。
-
DI(Dependence Injection):依赖注入,是IOC的的技术实现,只需要在程序中提供要使用的对象名称就可以;至于对象如何在容器中创建,赋值,查找都由容器内部实现,其底层原理是反射机制。
二、使用IOC创建对象
1. Java中创建对象的方式
- 构造方法(new)
- 反射
- 序列化
- 克隆
- 动态代理
- IOC(容器创建对象)
2. 使用xml配置文件创建对象
-
在spring主配置文件中使用
<bean>
标签为属性赋值。 -
使用IOC可以创建自定义类的对象,也可以创建非自定义类的对象。
-
同一个类可以使用多个
<bean>
标签创建不同名称的对象。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" 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">
<!-- 一个bean对应一个对象,id为创建的对象的名称,因此值唯一 -->
<bean id="object1" class="类的全名"></bean>
<bean id="object2" class="类的全名"></bean>
<!--spring可以创建已存在的非自定义的类,例如创建Java中的日期类对象-->
<bean id="mydate" class="java.util.Date"></bean>
</beans>
3. 使用注解创建对象
-
@Component():可以对任意类创建对象
语法:@Component(value="对象名称") 或 @Component("对象名称") 或 @Component() 使用方法:首先在spring主配置文件中加入组件扫描器(component-scan),之后直接在类名上方加入该注解即可。
@Component("myStudent") public class Student { } //未指定对象名称时,spring默认以类名首字母小写作为对象名 @Component() public class Student { }
-
@Repository():用在持久层类的上面,创建dao层的对象。
-
@Service():用在业务层上面,创建service层的对象。
-
@Controller():用在控制层上面,创建控制层的对象。
类和注解编写完成后需要在spring主配置文件中加入组件扫描器:
<context:component-scan base-package="类文件所在的包名" />
三、使用IOC为属性赋值
Spring规定Java中的基本类型和String类型的数据均为简单类型,其他的均为引用类型。
1. 使用xml配置文件为属性赋值
- set注入
前提:set注入,顾名思义是使用类中的setXXX()方法进行属性的赋值,赋值时Spring会自动调用对应类中的对应setXXX()方法,因此如果使用set注入方式为属性赋值,类中就必须有相应的setXXX()方法。
该方式是在<bean>
标签中使用<property>
标签,name的值为变量名称,value和ref为所要赋的目标值。
<bean id="对象名" class="类全名">
<!--简单类型:使用属性value-->
<property name="name" value="krain"/>
<property name="age" value="23"/>
<!--引用类型:使用属性ref-->
<property name="school" ref="myschool"/>
</bean>
- 含参构造注入
前提:使用对应类的含参构造方法为属性赋值。Spring在创建对象时调用含参构造方法同时为属性赋值,因此舒勇此方法是必须设置含参构造方法。
使用含参构造注入为属性赋值有以下几种方式:
1)使用标签的name属性
<!--使用name属性-->
<bean id="student" class="cn.krain.ba03.Student">
<constructor-arg name="name" value="张三"/>
<constructor-arg name="age" value="12"/>
<constructor-arg name="school" ref="myschool"/>
</bean>
2)使用标签的index属性
<constructor-arg>
标签中index属性的值为构造方法参数的顺序,从0开始。
<!--使用name属性-->
<bean id="student2" class="cn.krain.ba03.Student">
<constructor-arg index="0" value="李斯"/>
<constructor-arg index="1" value="21"/>
<constructor-arg index="2" ref="myschool"/>
</bean>
3)省略index属性
直接按构造方法的参数顺序赋值。
<!--使用name属性-->
<bean id="student3" class="cn.krain.ba03.Student">
<constructor-arg value="王五"/>
<constructor-arg value="34"/>
<constructor-arg ref="myschool"/>
</bean>
- 自动注入
Spring可以根据byName或byType规则自动给引用类型赋值。
1)byName(按姓名注入)
要求:java类中引用类型变量的名称和bean标签id的名称一样,且数据类型是一致的
语法:`<bean name="xxx" class="yyy" autowire="byName"></bean>`
2)byType(按类型注入)
java引用数据类型和spring容器中(配置文件)`<bean>`中的class的值是同源(同一类)关系
以下三种情况可用byType:
1)java类中引用类型的数据类型和bean的class的值是一类
2)java类中引用类型的数据类型和bean的class的值是父子类关系
3)java类中引用类型的数据类型和bean的class的值是接口与实现类的关系
注意事项:使用byType时,在xml配置文件中声明的bean只能有一个符合条件的,否则会报错
2. 使用注解为属性赋值
- @Value()
为简单赋值属性,直接在类中对应属性上方加入注解即可。
@Component("myStudent")
public class Student {
@Value("张飞")
private String name;
@Value("233")
private Integer age;
}
- @Autowired()
为引用类型属性赋值,有byName和byType两种方式,默认使用byType方式。
@Component("myStudent")
public class Student {
@Value("张飞")
private String name;
@Value("233")
private Integer age;
/* * 为引用数据类型赋值:自动注入 byType byName * @Autowired:默认使用的是byType自动注入 * * 使用byName时: * 1.在属性上面加入@Autowired * 2.在属性上面加入@Qualifier("属性名,即bean的id") * */
//使用byName
@Autowired
@Qualifier("mySchool") //引用类型数据的名称
private School school;
//使用byType,根据属性的类型自动赋值
@Autowired
private School school;
}
- @Resource()
JDK中的注解,使用自动注入为引用类型属性赋值,支持byName、byType,默认是byName。
@Component("myStudent")
public class Student {
@Value("张飞")
private String name;
@Value("244")
private Integer age;
/* * 使用@Resource:该注解来自jdk,spring框架提供了对这个注解的功能支持 * 同样是自动注入原理,支持byName byType,默认是byName * Resource会先使用byName注入,如果byName赋值失败,会自动使用byType */
//默认为byName
@Resource(name = "mySchool")
private School school;
//byType
@Resource()
private School school;
...
}
类和注解编写完成后需要在spring主配置文件中加入组件扫描器:
<context:component-scan base-package="类文件所在的包名" />