一、Spring IOC 容器
IOC(Inversion of Control) ,即控制反转。通常情况下我创建一个对象都是在程序中通过 new 关键字来完成的。在使用 Spring 框架后,对象的创建由 IOC 容器来完成。
二、Spring IOC 容器对 Bean 的管理
IOC 容器对 Bean 的管理主要体现在两个方面
- 创建对象
- 注入属性
IOC 容器对 Bean 的管理方式
IOC 容器对 Bean 的管理手段主要是:依赖注入,实现依赖注入的方式有如下形式:
1. 基于 xml 文件的方式
(1) xml 方式创建对象
该种方式在创建对象时,默认也是执行 User 类的无参构造方法来完成对象的创建。
public class User implements Serializable {
private String username;
public User() {
}
}
<bean id="user" class="com.sff.demo.bean.User"></bean>
(2) xml方式注入属性
- set方法注入属性
public class Student implements Serializable {
private String name;
public void setName(String name) {
this.name = name;
}
}
<bean id="student" class="com.sff.demo.bean.Student">
<!--
name:类里面的属性名称
value:向属性中注入的值
-->
<property name="name" value="Kate"></property>
</bean>
- 有参数构造器注入属性
public class Order implements Serializable {
private String orderNo;
private String address;
public Order(String orderNo, String address) {
this.orderNo = orderNo;
this.address = address;
}
}
<bean id="order" class="com.sff.demo.bean.Order">
<constructor-arg name="orderNo" value="JD009876"/>
<constructor-arg name="address" value="beijing"/>
</bean>
set方法 和 有参构造器 是属性注入的常用方式,利用这两种方式可以完成一些特殊属性的注入。
- 特殊字符和NULL值注入
public class Company implements Serializable {
private String id;
private String name;
public void setId(String id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
}
<bean id="company" class="com.sff.demo.bean.Company">
<!-- 给属性注入 null 值 -->
<property name="id"> <null/> </property>
<!-- 给属性注入特殊符号,比如注入:<航空科技有限公司>
1.使用 <![CDATA[]]> 2.使用转义符: < > -->
<property name="name">
<value> <![CDATA[<航空科技有限公司>]]> </value>
</property>
</bean>
- 外部Bean对象的注入
public class Bus implements Serializable {
private String busNo;
private Company company;
public void setBusNo(String busNo) {
this.busNo = busNo;
}
public void setCompany(Company company) {
this.company = company;
}
}
<bean name="busCompany" class="com.sff.demo.bean.Company">
<property name="name" value="北京公交公司"/>
</bean>
<bean name="bus" class="com.sff.demo.bean.Bus">
<property name="company" ref="busCompany"/>
<property name="busNo" value="空56路"/>
</bean>
- 数组、集合属性注入
主要是通过
<array> 、<list>、<set> 和 <map>
标签来完成
@Getter
@Setter
public class Collection implements Serializable {
private String[] arrays;
private List<String> lists;
private Set<String> sets;
private Map<String, String> maps;
}
<bean id="collection" class="com.sff.demo.bean.Collection">
<!--数组属性注入-->
<property name="arrays">
<array>
<value>aaa</value>
<value>bbb</value>
</array>
</property>
<!--list集合属性注入-->
<property name="lists">
<list>
<value>大哥</value>
<value>二哥</value>
</list>
</property>
<!--set集合属性注入-->
<property name="sets">
<set>
<value>15号线</value>
<value>5号线</value>
</set>
</property>
<!--map集合注入-->
<property name="maps">
<map>
<entry key="name" value="大飞"/>
<entry key="age" value="18"/>
</map>
</property>
</bean>
集合元素的注入除了使用 <array> 、<list>、<set> 和 <map>
标签,还可以使用
<utils:list/>、<utils:set/>、<utils:map/>
标签,使用该标签时要引入对应的命名空间
xmlns:utils="http://www.springframework.org/schema/util"
- 工厂方式注入
工厂方式注入属性时,我们可以利用工厂方法注入,也可以利用 Spring 的
FactoryBean
,它 Spring 提供的一个工厂类接口,通过实现该接口可以定制一些 Bean 实例化时的特殊逻辑。
定义一个Bean对象:
@Getter
@Setter
public class Car implements Serializable {
private String carName;
}
FactoryBean 方式:
public class CarBeanFactory implements FactoryBean<Car> {
@Override
public Car getObject() throws Exception {
Car car = new Car();
car.setCarName("奔驰");
return car;
}
@Override
public Class<?> getObjectType() {
return Car.class;
}
}
<bean name="car" class="com.sff.demo.bean.CarBeanFactory"></bean>
工厂方法方式:
// 简单工厂
public class CarFactory {
public Car getCar() {
Car car = new Car();
car.setCarName("宝马");
return car;
}
}
<!--工厂方法注入-->
<bean id="carFactory" class="com.sff.demo.bean.CarFactory"/>
<bean id="bwmCar" factory-bean="carFactory" factory-method="getCar"/>
- xml 中引入外部属性文件来实现 Bean 属性注入
<context:property-placeholder location="classpath:jdbc.propertiest">
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="username" value="${prop.username}"/>
<property name="password" value="${prop.password}"/>
</bean>
2. 基于注解的方式
基于注解的方式来管理 Bean 时,不管使用那种注解,首先要扫描到该注解所在的类的包路径,这里要使用到 <context:component-scan>
标签
<!-- 如果扫描多个包,多个包使用逗号隔开 -->
<context:component-scan base-package="com.sff.demo.ano"></context:component-scan>
- context:component-scan 标签的高级用法
<context:component-scan base-package="com.sff.demo.ano" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
表示只扫描 com.sff.demo.ano
包下带有 @Controller
注解的类。
<context:component-scan base-package="com.sff.demo.ano" use-default-filters="false">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Component"/>
</context:component-scan>
表示只要 com.sff.demo.ano
包下带有 @Component
注解的类都不会被扫描到。
- IOC 注解
@Component
@Controller
@Service
@Repository
- 依赖注入注解
@Autowired
@Resource
@Qualifier
@Value
@Autowired
注解:
默认按类型装配(byType),如果想实现按名称装配(byName),需要结合 @Qualifiler 注解使用(@Qualifiler根据属性名称进行注入),该注解是Spring自带的注解。(@Qualifier 注解还可以给方法参数注入)
@Resource
注解:
默认按名称装配(byName),可以通过 @Resource 的 name 属性指定名称,如果没有指定name属性,则按照字段的名称查找,找不到与字段名称匹配的bean时才会按照类型(byType)进行装配。但是如果name属性一旦指定,就只能安装name属性值装配。@Resource 主键属于 J2EE JSR250 规范中的注解,不是 Spring 自带的注解哦。
@Value
注解:
该注解只针对普通数据类型(比如:String、Integer 等)注入,而@Autowired @Resource @Qualifier
只针实体 Bean 对象注入。