Spring IOC容器之Bean管理
1 基于xml方式
- 在Spring配置文件中,在bean标签里面添加对应的属性,就可以实现对象的创建。
1.1 创建对象
- 配置文件,
1 |
|
- 读取配置文件,工厂方法创建对象,
1 | public class Test { |
1.2 注入属性
1.2.1 set方法
- 先要定义属性的set方法,
1 | public void setName(String name) { |
- 配置文件中在bean标签下使用property标签设置属性,
1 |
|
- 简化方式:p名字空间注入(不常用),
1 |
|
- 使用null标签注入空值,
1 | <property name="telephone"> |
- 使用xml CDATA注入特殊字符,
1 | <property name="favoriteBook"> |
1.2.2 有参构造函数
- 先要定义类的有参构造函数,
1 | public User(String name, String address) { |
- 配置文件中在bean标签下使用constructor-arg标签初始化对象,
1 |
|
1.2.3 外部bean
- 通常一个类会包含对象属性,
1 | public class UserService { |
例如上面的代码,UserService类中就包含了一个UserDao对象
- 如果需要初始化类内的对象属性,可以使用ref以外部bean的形式配置,
1 | <bean id="userDao" class="com.company.dao.UserDaoImpl"></bean> |
1.2.4 内部bean
- 也可以在property标签内部初始化对象属性,这种方式被称为内部bean,
1 | <bean id="userService" class="com.company.service.UserService"> |
1.2.5 级联赋值
1 | <bean id="userService" class="com.company.service.UserService"> |
- 需要提前定义好get和set方法,否则会报错
- 先在UserService对象中创建UserDao对象,然后调用get方法获得UserDao对象,最后调用setName方法为name属性赋值
1.2.6 集合属性
- 提前定义好属性的set方法,
1 | public class Student { |
1.2.6.1 数组
1 | <property name="courses"> |
1.2.6.2 List集合
1 | <property name="nicknames"> |
1.2.6.3 Map集合
1 | <property name="contactMethod"> |
1.2.6.4 Set集合
1 | <property name="friends"> |
1.2.6.5 在集合里面设置对象类型值
- 有时集合属性中存放的是对象,
1 | public class BookShelf { |
- 使用ref标签初始化集合属性内部存放的对象,
1 | <bean id="book1" class="com.company.Book"> |
1.2.6.6 把集合注入部分提取出来
- 修改xml文件头部的配置,
1 | <beans xmlns="http://www.springframework.org/schema/beans" |
- 使用util标签将集合注入部分提取出来,
1 | <bean id="book1" class="com.company.Book"> |
- 引用被抽取出的集合,
1 | <bean id="bookShelf" class="com.company.BookShelf"> |
1.3 工厂bean
- 对于工厂bean,配置文件中定义的bean类型可以和返回类型不一样
- 第一步:创建类,让这个类实现接口FactoryBean,作为工厂bean
- 第二步:实现接口声明的方法,在实现的方法中定义返回的对象类型,
1 | public class FacBean implements FactoryBean<Book> { |
- 配置文件,
1 |
|
bean标签定义的类型为FacBean,但是实际getBean方法返回的对象类型是Book
1.4 bean的作用域
- 在Spring里面,默认情况下,bean是单实例对象
- bean标签scope属性的取值,
是否单例 | 对象创建的时机 | |
---|---|---|
singleton | 是 | Spring加载配置文件时 |
prototype | 否 | 调用getBean方法时 |
1.5 bean的生命周期
1.5.1 过程
- 通过构造器创建bean实例
- 调用set方法为bean的属性设置值和对其他bean引用
- 将bean对象传递给bean后置处理器的postProcessBeforeInitialization方法
- 调用bean的初始化方法(需要配置初始化方法)
- 将bean对象传递给bean后置处理器的postProcessAfterInitialization方法
- bean可以被使用(对象获取到了)
- 当容器关闭时,调用bean的销毁方法(需要配置销毁的方法)
1.5.2 配置bean的初始化方法
- 为类定义一个方法,作为bean的初始化方法,
1 | public void initMethod() { |
- 在bean标签中使用init-method属性配置bean的初始化方法,
1 | <bean id="order" class="com.company.cycle.Order" init-method="initMethod" destroy-method="destroyMethod"> |
1.5.3 配置bean的销毁方法
- 为类定义一个方法,作为bean的销毁方法,
1 | public void destroyMethod() { |
- 在bean标签中使用destroy-method属性配置bean的销毁方法,
1 | <bean id="order" class="com.company.cycle.Order" init-method="initMethod" destroy-method="destroyMethod"> |
- destroyMethod在容器关闭的时候被调用,
1 | ((ClassPathXmlApplicationContext)context).close(); |
1.6 xml自动装配
- 假设存在Employee类和Department类,
1 | public class Employee { |
1.6.1 按名字
- 在bean标签中将autowire属性配置为byName,
1 | <bean id="employee" class="com.company.Employee" autowire="byName"> |
1.6.2 按类型
- bean标签中将autowire属性配置为byType,
1 | <bean id="employee" class="com.company.Employee" autowire="byType"> |
1.7 外部属性文件
- 使用“user.properties”配置文件初始化User对象,
1 | user.name="Lihua" |
- 在xml配置文件头部添加context名字空间,
1 |
|
- 引用外部配置文件注入属性,
1 | <context:property-placeholder location="classpath:user.properties"></context:property-placeholder> |
使用“$”符号引用外部配置文件的内容,必须保证大括号内和配置文件中的key一致
2 基于注解方式
2.1 Spring创建对象的注解
- @Component,通用注解
- @Service,通常用在Service层
- @Controller,通常用在Web层
- @Repository,通常用在DAO层
以上四个注解功能是一样的,都可以用来创建bean实例
2.2 创建对象
2.2.1 开启组件扫描
- 可以使用逗号隔开多个包,
1 | <context:component-scan base-package="com.company.dao, com.company.service"></context:component-scan> |
- 也可以将上层的包作为参数(底层的包都会被扫描),
1 | <context:component-scan base-package="com.company"></context:component-scan> |
2.2.2 添加注解
1 |
|
- 注解括号内的value相当于xml配置文件bean标签的id属性
- 注解的value值可以不指定,默认值是将类名首字母小写
2.3 组件扫描配置
2.3.1 只扫描指定的注解
1 | <context:component-scan base-package="com.company" use-default-filters="false"> |
- 默认情况下,Spring将扫描base-package包下所有的类
- 如果配置use-default-filters为false,那么Spring将根据配置进行组件扫描
- 使用context:include-filter标签可以指定将被扫描的注解
2.3.2 不扫描指定的注解
1 | <context:component-scan base-package="com.company"> |
- 使用context:exclude-filter标签可以指定某些注解不被扫描
2.4 注入属性
2.4.1 Autowired
- @Autowired注解根据属性的类型自动装配,
1 |
|
在userDao属性上注解@Autowired,Spring将在组件扫描的包内搜寻符合条件的类型创建对象。在这个例子中,Spring找到UserDaoImpl是UserDao的实现类,符合条件
2.4.2 Qualifier
- 在上面的例子中,如果UserDao接口有多个实现类,仅通过@Autowired注解自动装配会产生冲突,因为Spring不知道该创建哪个实现类的对象
- 这个时候可以使用@Qualifier注解指定实现类,
1 |
|
@Qualifier注解括号内的value必须和实现类注解括号内的value相同
2.4.3 Value
- 使用@Value注解可以注入非对象类型的属性,
1 |
|
2.5 完全注解开发
2.5.1 配置类
- 创建配置类,替代xml配置文件,
1 |
|
2.5.2 加载配置类,创建对象
1 | ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); |
- 只需要将context的实现类替换成AnnotationConfigApplicationContext,将配置类的类型作为参数即可