Ioc本质
控制反转Ioc,是一种设计思想,而不是一种新的技术。DI(依赖注入)是实现Ioc的一种方法,也有人认为DI只是Ioc的另一种说法。在没有Ioc的程序中,使用面向对象编程,对象的创建与对象之间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方发,控制反转就是:获得以来对象的方式反转了。
Ioc是spring框架的核心内容,使用多种方式完美的实现了Ioc,可以使用XML配置,也可以使用注解,新版本的spring可以零配置实现Ioc.
spring容器在初始化时先读取配置文件,根据配置文件或元数据创建与组织对象存入容器中,程序使用时再从Ioc容器中取出需要的对象
采用XML方式配置bean的时候,bean的定义信息和实现分离的,而采用注解的方式把二者合为一体,bean的定义信息直接以注解的形式的定义在实体类中,从而达到了零配置的目的。
控制反转是一种通过描述(XML或注解)并通过第三方去生产获取特定对象的方式。在spring中实现控制反转的是Ioc容器,其实现方法是依赖注入(DI)
依赖注入
指spring创建对象的过程中,将对象依赖属性(常量,对象,集合)通过配置设置给该对象。
依赖注入的方式
- 构造方法注入
- set方法注入
- P命名空间注入
构造方法注入
StudentServiceImpl中提供有参构造
public class StudentServiceImpl implements StudentService {
private StudentDao studentDao;
public StudentServiceImpl(StudentDao studentDao) {
this.studentDao = studentDao;
}
//set方法注入
/*public void setStudentDao(StudentDao studentDao) {
this.studentDao = studentDao;
}*/
@Override
public void getStudent() {
studentDao.getStudent();
}
}
修改配置文件
在bean标签中提供了一个子标签来完成构造方法的注入
构造方法的注入有两种方式
<!--依赖注入 通过构造注入方式一-->
<!--
name:构造方法参数名称
value:简单数据类型
ref:应用数据类型(从IOC容器中获取的对象)
-->
<!--配置studentDao的实现类studentDaoImpl-->
<bean id="studentDao" class="com.lifly.dao.impl.StudentDaoImpl"></bean>
<!--配置studentService的实现类studentServiceImpl-->
<bean id="studentService" class="com.lifly.service.impl.StudentServiceImpl">
<constructor-arg name="studentDao" ref="studentDao"></constructor-arg>
</bean>
通过构造注入第二种不常用仅了解即可
<!--依赖注入 通过构造注入方式一(二)-->
<!--
index:构造方法参数索引
type:该索引的java类型
value:简单数据类型
ref:引用数据类型(从IOC容器中获取的对象)
-->
<bean id="studentDao" class="com.lifly.dao.impl.StudentDaoImpl"></bean>
<!--配置studentService的实现类studentServiceImpl-->
<bean id="studentService" class="com.lifly.service.impl.StudentServiceImpl">
<constructor-arg index="0" type="com.lifly.dao.StudentDao" ref="studentDao"></constructor-arg>
</bean>
set 方法注入
在StudentServiceImpl中提供set方法
public class StudentServiceImpl implements StudentService {
private StudentDao studentDao;
/* public StudentServiceImpl(StudentDao studentDao) {
this.studentDao = studentDao;
}*/
//set方法注入
public void setStudentDao(StudentDao studentDao) {
this.studentDao = studentDao;
}
@Override
public void getStudent() {
studentDao.getStudent();
}
}
修改配置文件
使用set方法注入,提供一个子标签,完成set方法注入
<!--setter方法注入-->
<!--
name:set方法的属性名去掉set,首字母小写
value:简单数据类型
ref:引用数据类型(从IOC容器中获取)
-->
<bean id="studentDao" class="com.lifly.dao.impl.StudentDaoImpl"></bean>
<bean id="studentService" class="com.lifly.service.impl.StudentServiceImpl">
<property name="studentDao" ref="studentDao"/>
</bean>
P命名空间注入
P命名空间注入底层(本质)使用的也是set方法注入,只是在上面的基础上简化
使用P命名空间注入,需要先倒入约束
xmlns:p=“http://www.springframework.org/schema/p”
与set方法注入一样,只需要在xml配置文件中修改配置文件即可
<!--p命名空间注入-->
<bean id="studentDao" class="com.lifly.dao.impl.StudentDaoImpl"></bean>
<bean id="studentService" class="com.lifly.service.impl.StudentServiceImpl" p:studentDao-ref="studentDao"></bean>
依赖注入的数据类型
注入简单类型
定义一个JavaBean例如Person类
public class Person {
//基本数据类型
private String username;
private int age;
// 单列集合 array list set
private String[] array;
private List<String> list;
private Set<String> set;
// 双列集合 map,properties
private Map<String,String> map;
private Properties properties;
//get和set方法
//有参无参构造
@Override
public String toString() {
return "Person{" +
"username='" + username + '\'' +
", age=" + age +
", array=" + Arrays.toString(array) +
", list=" + list +
", set=" + set +
", map=" + map +
", properties=" + properties +
'}';
}
}
编写配置文件
DI注入简单类型
<!--Di注入简单数据类型-->
<bean id="person" class="com.lifly.bean.Person">
<property name="username" value="lifly"/>
<property name="age" value="24"/>
DI注入单列集合
<!--注入单列集合 array list set-->
<property name="list">
<list>
<value>峡谷之巅</value>
<value>黑色玫瑰</value>
<value>弗雷尔卓德</value>
</list>
</property>
<property name="array">
<array>
<value>德玛西亚</value>
<value>艾欧尼亚</value>
<value>乱葬之海</value>
</array>
</property>
<property name="set">
<set>
<value>古力娜扎</value>
<value>迪丽热吧</value>
<value>马尔扎哈</value>
</set>
</property>
Di注入双列集合
<!--注入双列集合-->
<property name="map">
<map>
<entry key="天" value="地"></entry>
<entry key="人" value="和"></entry>
</map>
</property>
<property name="properties">
<props>
<prop key="大桥">孙策</prop>
<prop key="小乔">周瑜</prop>
<prop key="香香">刘备</prop>
</props>
</property>
spring核心接口
- BeanFactory
Ioc的*接口,它定义了Ioc最基础的功能,但是其功能比较简单,一般面向spring自身使用
特点:在第一次使用到某个Bean(调用getBean())才对该Bean进行加载实例(用的时候再创建)-----》懒汉设计模式
- ApplicationContext
这是在BeanFactory基础上衍生出的接口,它扩展了BeanFactory的功能,一般面向程序员使用
特点:在容器启动时,一次性创建并加载所有的Bean(初始化的时候全部创建好)—》饿汉设计模式
spring核心实现类
- ClassPathXmlApplicationContext
读取类路径(classpath)下的xml配置文件
- FileSystemXmlApplicationContext
读取本地磁盘下的xml配置文件
- AnnotationConfigApplicationContext
读取java配置类加载配置
spring核心方法
- getBean(String name)
通过指定id获取对象的实例,需要手动强转
例如以下代码
//读取applicationContext核心配置文件
//通过指定id获取对象的实例,需要要手动强转
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
//获取UserDao
UserDao userDao = (UserDao) classPathXmlApplicationContext.getBean("userDao");
userDao.getUser();
- getBean(ClassrequiredType)
通过指定类型获取对象的实例,不需要强制转换
例如以下代码
/**
* getBean(Class<T>requiredType)
* 如果同一个接口类型下有多个实力对象,会报错
* org.springframework.beans.factory.NoUniqueBeanDefinitionException:
* No qualifying bean of type 'com.lifly.dao.UserDao' available:
* expected single matching bean but found 2: userDao,userDaoMysql
*/
@Test
public void springQucikTest2(){
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao = classPathXmlApplicationContext.getBean(UserDao.class);
userDao.getUser();
}
- getBean(String name,ClassrequiredType)
通过指定id和类型获取对象的实例
例如以下代码
/**
* getBean(String name,Class<T>requiredType)
* 通过指定id和类型获取对象的实例
*/
@Test
public void springQucikTest3(){
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDaoMysql = classPathXmlApplicationContext.getBean("userDaoMysql", UserDao.class);
userDaoMysql.getUser();
}
spring配置文件
Bean标签配置
相关属性
属性名 | 描述 |
---|---|
id | 在Ioc容器的唯一标识 |
class | 创建对象实例的权限定名 |
scope | 声明此对象的作用范围 singleton:单例对象(默认) prototype:多利对象 |
init-method | 在对象创建时,执行此方法 |
destory-method | 在对象销毁时,执行此方法 |
作用范围
1. singleton(单例对象)
何时创建:ioc容器初始化时,创建对象
对象何时运行:只要ioc容器在,对象就一直存在
何时销毁:ioc容器关闭时,销毁对象2. prototype(多例对象)
何时创建:在调用getBean()方法时,创建
对象运行:一直使用就一直活着
何时销毁:当对象不再使用后,根据JVM,GC机制垃圾回收