5分钟搞懂Spring IOC
前言
下面的内容均以xml举例说明,因为ioc只是一种思想。
概念
众所周知,Spring是一个对象管理容器,自动化完成了创建、初始化、销毁等工作。
IOC(控制反转)是一个概念,是一种思想,其实现方式多种多样。当前比较流行的实现方式之一是DI(依赖注入)。就酱,ioc是思想,DI是手段。
基于XML的DI
XML文件结构
ApplicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
// xmlns 类似于java中的package
// xsi 是指xml遵守xml规范,xsi全名xml schema instance
// xsi:schemaLocation 是指具体用到的schema资源
<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="food" class="com.andy.Food"></bean>
</beans>
Bean的定义与注册
Spring的配置文件是用于指导Spring工厂进行Bean的生产、依赖关系注入及Bean实例分发的“图纸”,它是一个或多个标准的XML文档
<bean id="food" class="com.andy.Food"></bean>
spring ioc container
spring ioc container 管理一个或多个bean,bean来自xml中对bean定义的元数据(configuration metadata)
Class | 类 |
---|---|
Name,id | 标识 |
Scope | 作用域 |
Constructor arguments | 构造器注入 |
Properties | 属性注入 |
autowiring mode | 自动装配 |
lazy-initialization mode | 懒加载 |
initialization method | 初始化 |
destruction method | 销毁 |
构造器注入
// Person类全参构造器
Person(String name, Integer age) {
super();
this.name = name;
this.age = age;
}
<!-- xml方式指定age/name 构造器注入-->
<bean id="person" class="com.msb.Person">
<constructor-arg name="age" value="18"></constructor-arg>
<constructor-arg name="name" value="zhangsan"></constructor-arg>
</bean>
属性注入
<!-- xml方式指定age/name 属性值注入-->
<bean id="person" class="com.msb.Person">
<property name="age" value="19"></property>
<property name="name" value="zhangsan"></property>
</bean>
工厂方式注入
为满足更复杂的需求,Spring也提供了工厂方式来创建更加灵活的Bean
动态工厂
// 抽象工厂Car
public interface Car {
public String getName();
public String getPrice();
}
// 实现类
public class Benz implements Car{
public String getName() {
// TODO Auto-generated method stub
return "梅赛德斯奔驰";
}
public String getPrice() {
// TODO Auto-generated method stub
return "300000RMB";
}
}
}
// 汽车工厂类
public class CarFactory {
public Car getCar(String name) throws Exception{
if (name.endsWith("梅赛德斯奔驰")) {
return new Benz();
}else {
throw new Exception("car not fond");
}
}
}
<!-- bean 配置-->
<bean id="carFactory" class="com.andy.CarFactory"></bean>
<bean id="car" factory-bean="carFactory" factory-method="getCar" >
<constructor-arg value="benz"></constructor-arg>
</bean>
静态工厂
public class CarFactoryStatic {
public static Car getCar(String name) throws Exception{
if (name.endsWith("benz")) {
return new Benz();
}else {
throw new Exception("car not fond");
}
}
}
autowire自动注入
public class Person {
private String name;
private Pet pet;
}
public class Pet {
private String name;
}
<bean id="person" class="com.andy.Person" autowire="byName">
</bean>
<!-- 宠物 -->
<bean id="coffee" class="com.andy.Pet">
<property name="name" value="coffee"></property>
</bean>
byName
byName方式自动注入:要求注入的bean的id必须和被注入的bean对象的属性名一致
byType
byType方式自动注入:要求注入的bean的对象类型与被注入的bean对象类型一致,并且在配置文件中的Bean相同类型必须唯一
如果存在多个,会抛异常
全局自动注入
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"
default-autowire="byType"
>
注解注入
使用注解需要导入AOP包
在配置文件中添加Context约束
开启context:component-scan
@Controller@Component@Service @Autowired @Value 等等
作用域(6种)
container-aware
singleton scope: 单例作用域,每个类,在容器内只能产生一个实例
prototype scope: 原型作用域,该bean每次被注入,或者使用GetBean()方法获取时,都会返回新实例
web-aware
request scope: 该作用域下的bean,在每个HTTP request都会新建一个实例,当一个request结束后,该实例也会被丢弃
session scope:一个用户在一段时间内,会使用同一个session,session有超时时间,过了超时时间则session失效。不同用户使用不同的session
application scope: 该作用域的bean,每一个application会创建一个