IoC就是通过容器来实现对象的装配与管理,当下比较流行的主要有两种实现方式:依赖注入和依赖查找。
- 依赖查找(DL):容器提供回调接口和上下文环境给组件,程序代码则需要提供具体的查找方式。比较典型的是依赖于JNDI系统的查找。
- 依赖注入(DI):程序代码不做定位,这些工作全都是由容器自行完成(比较常用)
怎么去理解依赖注入呢?也就是我们在逻辑代码中假如要使用到一个对象Student,此时我们不用new一个Student,我们只需要在配置文件中声明加载到容器中,通过容器将Student给调用者。
接下来看看如何使用IOC。先给出整个项目目录:
一、导入jar包
首先我们导入四个基本jar包,然后导入三个日志相关的jar包
二、定义接口与实现类
先看接口:
package com.fdd.service;
public interface ISomeService {
public void doSome();
}
实体类如下:
package com.fdd.service;
public class SomeServiceImpl implements ISomeService {
public void doSome() {
System.out.println("doSome实现");
}
}
三、创建Spring配置文件
在这里我们创建applicationContext.xml,
<?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">
<!-- 注册Service-->
<bean id="myService" class="com.fdd.service.SomeServiceImpl"/>
</beans>
<bean/>用于定义一个实例对象,一个实例对应一个bean元素
四、定义测试类
@Test
public void test02(){
//创建容器对象,记载Spring配置文件,会从类路径下面查找文件也就是src下面
ApplicationContext ac= new ClassPathXmlApplicationContext("applicationContext.xml");
//创建容器对象,记载Spring配置文件,会从项目路径下面查找文件也就是src同级目录
//ApplicationContext ac= new FileSystemXmlApplicationContext("applicationContext.xml");
//从容器中获取对象
ISomeService service = (ISomeService) ac.getBean("myService");
service.doSome();
}
运行结果如下
上面使用的是ApplicationConetext接口容器,看一看其实现:
A:配置文件在类路径下面
//创建容器对象,记载Spring配置文件,会从类路径下面查找文件也就是src下面
ApplicationContext ac= new ClassPathXmlApplicationContext("applicationContext.xml");
B:配置文件在本地目录
如果配置文件在本地磁盘的其他路径,或者是放在项目的根路径下面。那么使用下面这种方式来实现
//创建容器对象,记载Spring配置文件,会从项目路径下面查找文件也就是src同级目录
//ApplicationContext ac= new FileSystemXmlApplicationContext("applicationContext.xml");
五、分析两个接口容器
上面在测试类的时候使用的是ApplicationContext接口容器。还有一种spring容器,叫做BeanFactory,它是ApplicationContext接口容器的父类。
其实现方式可以这个样:
@Test
public void test03(){
@SuppressWarnings("deprecation")
BeanFactory bf=new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
ISomeService service = (ISomeService) bf.getBean("myService");
service.doSome();
}
虽然这两个接口容器加载的是同一个Spring配置文件。但是在代码中这两个容器对象却不是同一个对象,也不是同一个容器:这是因为他们对于容器内对象的装配时机是不一样的。
在测试两个容器对象的装配时机的时候需要注意,需要在SomeServiceImpl类的无参构造器中添加一个输出语句。以显示是否执行:
package com.fdd.service;
public class SomeServiceImpl implements ISomeService {
//添加无参构造器
public SomeServiceImpl() {
System.out.println("无参构造器:SomeServiceImpl实现类");
}
public void doSome() {
System.out.println("doSome实现");
}
}
A:ApplicationContext容器中对象的装配时机
ApplicationContext容器会在容器对象初始化时候,将其中的所有对象一次性全部装配好,以后代码中如果需要使用到这些对象,只需要直接从内存中获取即可。。执行效率比较高,但是超级占用内存。
B:BeanFactory容器中对象的装配时机
BeanFactory容器,对容器中对象的装配与加载采用延迟加载策略,也就是在第一次调用getBean()时,才真正的装配该对象。