目录
1 第二天 MyBatis+Spring 2
1.1 *动态SQL语句 3
1.1.1
1.1.2
1.1.3
1.2 集合参数
1.2.1 数组array 9
1.2.2 List集合 10
1.2.3 Map/HashMap集合 11
1.3 Mapper接口的实现 11
1.3.1 特点 11
1.3.2 修改映射文件 11
1.3.3 创建UserMapper接口 12
1.3.4 创建测试类 12
1.4 MyBatis拓展 12
1.4.1 Mybatis怎么做的? 12
1.4.1 配置别名 12
1.4.2 SQL中有特殊字符 13
1.5 =====spring 13
1.6 初识Spring框架 13
1.6.1 Spring的野心 13
1.6.2 介绍 14
1.6.3 核心架构 14
1.6.4 核心组件 16
1.6.5 主要jar组成 16
1.7 IoC控制反转 17
1.7.1 概述 17
1.7.2 入门案例 - 创建Maven工程 17
1.7.3 pom.xml 17
1.7.4 创建Hello.java 18
1.7.5 applicationContext.xml 18
1.7.6 TestIoC.java 18
1.7.7 小结 18
1.8 Bean对象的多实例 18
1.8.1 概述 18
1.8.2 applicationContext.xml 18
1.8.3 TestIoC.java 19
1.9 扩展 19
1.9.1 导入约束自动提示 19
1.9.2 面试:IoC和DI 22
第二天 MyBatis+Spring
!!动态SQL语句
Mybatis提供使用ognl表达式动态生成sql的功能。


和
Sql标签:提取SQL片段,提高SQL片段的复用性
Include标签:引用SQL片段
映射文件
<?xml version=“1.0” encoding=“UTF-8”?>
<!DOCTYPE mapper
PUBLIC “-//mybatis.org//DTD Mapper 3.0//EN”
“http://mybatis.org/dtd/mybatis-3-mapper.dtd">
id,name,addr,age
resultType=“User”>
select
from user
测试类
package cn.tedu.test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;
import cn.tedu.pojo.User;
public class DongtaiSqlTest {
//声明工厂,线程安全<br /> SqlSessionFactory ssf =**null**;<br /> <br /> @Before//在@Test之前执行,完成初始化<br /> **public** **void** init(){<br /> **try** {<br /> //加载核心配置文件<br /> InputStream in = <br /> Resources._getResourceAsStream_(<br /> "sqlMapConfig.xml");<br /> <br /> //创建ssf<br /> ssf = **new** SqlSessionFactoryBuilder()<br /> .build(in);<br /> <br /> } **catch** (IOException e) {<br /> e.printStackTrace();<br /> }<br /> <br /> <br /> }<br /> <br /> <br /> @Test<br /> **public** **void** sqlInclude(){<br /> //创建会话<br /> SqlSession session = ssf.openSession();<br /> <br /> //定位SQL并执行<br /> List<User> list =<br /> session.selectList(<br /> "DynamicSqlMapper.SelectAll");<br /> <br /> //遍历list<br /> **for** (User user : list) {<br /> System._**out**_.println(user);<br /> }<br /> <br /> <br /> //释放资源<br /> session.close();<br /> }<br /> <br />}
映射文件
<?xml version=“1.0” encoding=“UTF-8”?>
<!DOCTYPE mapper
PUBLIC “-//mybatis.org//DTD Mapper 3.0//EN”
“http://mybatis.org/dtd/mybatis-3-mapper.dtd">
id,name,addr,age
resultType=“User”>
select
from user
id=#{id}
测试类
@Test
public void wheretest(){
//创建会话
SqlSession session = ssf.openSession();
//定位SQL并执行
List
session.selectList(
“DynamicSqlMapper.SelectAll”,28);
//遍历list
for (User user : list) {
System.out.println(user);
}
//释放资源
session.close();
}
还可以看到,如果配合where标签使用,where标签可以去除多余的and或者or等。
test属性里写的是属性名字,可不是字段名字!!
映射文件
<?xml version=“1.0” encoding=“UTF-8”?>
<!DOCTYPE mapper
PUBLIC “-//mybatis.org//DTD Mapper 3.0//EN”
“http://mybatis.org/dtd/mybatis-3-mapper.dtd">
id,name,addr,age
resultType=“User”>
select
from user
id=#{id}
and name=#{name}
测试类
@Test
public void wheretest(){
//创建会话
SqlSession session = ssf.openSession();
//定位SQL并执行
User user = new User();
// user.setId(28);不设置id值
user.setName(“jack”);
List
session.selectList(
“DynamicSqlMapper.SelectAll”,user);
//遍历list
for (User u : list) {
System.out.println(u);
}
//释放资源
session.close();
}
集合参数
数组array
映射文件:
resultType=“User”>select from user
where id in
open=“(“
close=“)”
separator=“,”>
#{i}
#### 测试类:
//批量查询,数据封装成array格式
@Test
public void batcharray(){
//创建会话
SqlSession session = ssf.openSession();
//定位SQL并执行
List
session.selectList(
“DynamicSqlMapper.batcharray”,
//批量查询时,需要array类型,所以把数据封装成int类型数组
new int[]{22,23,25,28});
//遍历list
for (User u : list) {
System.out.println(u);
}
//释放资源
session.close();
}
### List集合 #### 映射文件:
测试类:
@Test
public void foreachlist(){
SqlSession session = ssf.openSession();
List list = new ArrayList();
list.add(23);
list.add(25);
list.add(24);
//批量查询时,需要list类型,所以把数据封装成List类型
List
for (User user : ulist) {
System.out.println(user);
}
session.close();
}
Map/HashMap集合
映射文件:
测试类:
//批量查询,数据封装成map格式<br /> @Test<br /> **public** **void** foreachMap(){<br /> //创建会话<br /> SqlSession session = <br /> ssf.openSession();<br /> <br /> <br /> //定位SQL并执行<br /> Map map = **new** HashMap();<br /> map.put("key",**new** **int**[]{23,24,25});<br /> <br /> //第一个参数用来定位SQL<br /> //第二个参数用来给SQL传参,map类型<br /> List<User> list = <br /> session.selectList(<br /> "DynamicSqlMapper.foreachmap", <br /> **map**);<br /> <br /> //遍历list<br /> **for** (User user : list) {<br /> System._**out**_.println(user);<br /> }<br /> <br /> //释放资源<br /> session.close();<br /> <br /> <br /> }<br /> <br />
!!!!Mapper接口的实现
在上面的测试用例中,在调用session的方法的时候,都会传入要调用的SQL的namespace+id名称,这不是必须的。可以只传入id即可。但是,如果在mybatis的环境中有多个相同id的映射名称,就会报错。所以,一般情况下,调用方法最好还是使用namespace+id。但是,namespace+id的使用方式很容易报错,因为是string类型的,没有检查。所以,mybatis提供了一种非常好的设计方式来避免这种问题,即Mapper接口。
特点
1、 Mapper接口方法名和mapper.xml中定义sql的id值相同
2、 Mapper接口方法接收的参数类型和mapper.xml中定义的sql 的parameterType的类型相同
3、 Mapper接口方法的返回值类型和mapper.xml中定义的sql的resultType的类型相同
修改映射文件
创建UserMapper接口


package cn.tedu.dao;
import java.util.List;
import cn.tedu.pojo.User;
/1、 Mapper接口方法名和mapper.xml中定义sql的id值相同
2、 Mapper接口方法接收的参数类型和mapper.xml中定义的sql 的parameterType的类型相同
3、 Mapper接口方法的返回值类型和mapper.xml中定义的sql的resultType的类型/
public interface UserMapper {
<br /> //接口的方法名=sql的id值<br /> //接口方法的返回值类型=resultType类型<br /> //接口方法的参数=parameter类型<br />//<select id="SelectAll" resultType="cn.tedu.pojo.User"><br /> **public** List<User> SelectAll();<br /> <br /> //<select id="SelectOne" resultType="User"><br /> //select * from user where id=#{id}<br /> public User SelectOne(Integer id);<br /> <br /> //<select id="Count" resultType="int"><br /> **public** **int** Count();<br /> <br /> //<insert id="Add"><br /> //insert into user values<br /> //(#{id},#{name},#{addr},#{age})<br /> **public** **void** Add(User user);<br /> <br /> //<update id="update"><br />// update user set<br />// age=#{age} where<br />// id=#{id}<br /> **public** **void** update(User user);<br /> <br />// <delete id="delete"><br />// delete from user where id=#{id}<br /> **public** **void** delete(Integer id);<br />}
创建测试类
package cn.tedu.test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;
import cn.tedu.dao.UserMapper;
import cn.tedu.pojo.User;
public class InterfaceTest {
// 声明工厂,线程安全<br /> SqlSessionFactory ssf = null;
@Before // 在@Test之前执行,完成初始化<br /> public void init() {<br /> try {<br /> // 加载核心配置文件<br /> InputStream in = Resources.getResourceAsStream("sqlMapConfig.xml");
// 创建ssf<br /> ssf = new SqlSessionFactoryBuilder().build(in);
} catch (IOException e) {<br /> e.printStackTrace();<br /> }
}
// 测试接口定义的SelectOne方法<br /> @Test<br /> public void SelectOne() {<br /> // 创建会话<br /> SqlSession session = ssf.openSession();
// 调用接口,调用指定的接口<br /> UserMapper dao = session.getMapper(UserMapper.class);<br /> // 调用接口里的方法<br /> User user = dao.SelectOne(25);<br /> System.out.println(user);<br /> }
// 测试接口定义的SelectAll方法<br /> @Test<br /> public void SelectAll() {<br /> // 创建会话<br /> SqlSession session = ssf.openSession();
// 调用接口,调用指定的接口<br /> UserMapper dao = session.getMapper(UserMapper.class);<br /> // 调用接口里的方法<br /> List<User> list = dao.SelectAll();<br /> for (User user2 : list) {<br /> System.out.println(user2);<br /> }
}
// 测试接口定义的Count方法<br /> @Test<br /> public void Count() {<br /> // 创建会话<br /> SqlSession session = ssf.openSession();
// 调用接口,调用指定的接口<br /> UserMapper dao = session.getMapper(UserMapper.class);<br /> // 调用接口里的方法<br /> int i = dao.Count();<br /> System.out.println(i);
}<br /> <br /> // 测试接口定义的Add方法<br /> @Test<br /> public void Add() {<br /> // 创建会话<br /> SqlSession session = ssf.openSession(**true**);<br /> <br /> // 调用接口,调用指定的接口<br /> UserMapper dao = session.getMapper(UserMapper.class);<br /> <br /> //准备参数<br /> User user=new User();<br /> user.setName("test2");<br /> user.setAddr("bj");<br /> user.setAge(30);<br /> // 调用接口里的方法<br /> dao.Add(user);<br /> <br /> }<br /> <br /> // 测试接口定义的update方法<br /> @Test<br /> public void update() {<br /> // 创建会话<br /> SqlSession session = ssf.openSession(**true**);<br /> <br /> // 调用接口,调用指定的接口<br /> UserMapper dao = session.getMapper(UserMapper.class);<br /> <br /> //准备参数<br /> User user=new User();<br /> user.setAge(30);<br /> user.setId(28);<br /> // 调用接口里的方法<br /> dao.update(**user**);<br /> <br /> }<br /> // 测试接口定义的delete方法<br /> @Test<br /> public void delete() {<br /> // 创建会话<br /> SqlSession session = ssf.openSession(**true**);<br /> <br /> // 调用接口,调用指定的接口<br /> UserMapper dao = session.getMapper(UserMapper.class);<br /> <br /> ** ****// 调用接口里的方法**<br />** dao.delete(28);**<br /> <br /> }
}
MyBatis拓展
Mybatis怎么做的?
@Test<br /> public void testMapper(){<br /> SqlSession session = MyBatisUtil.openSession();<br /> try{<br /> UserMapper mapper = session.getMapper(UserMapper.class);<br /> System.out.println(mapper.getClass().getName());<br /> }finally{<br /> session.close();<br /> }<br /> }
打印结果:
$Proxy4
很简单了,mybatis为接口做了一个动态代理。在执行UserMapper接口上面的方法时,参考接口的全路径名,即可找到对应的UserMapper.xml,在执行接口上面的每一个方法的时候,实际上就是在执行namespace+id,mybatis在根据定义的方法的元素,选择调用合适的session的方法来执行,并传入参数就可以。
使用Mapper接口的方式,在集成Spring+MyBatis也非常方便。因为我们可以直接把Mapper接口看作domain的dao接口了。
配置别名
在sqlMapConfig.xml配置,在映射文件中直接写对象名称即可
在映射文件中可以省略实体对象的全路径,直接用别名就行
resultType=“User“>
select * from user where name=#{name}
SQL中有特殊字符
当SQL中有特殊字符,mybatis不能正常解析时,用CDATA括起来
<![CDATA[ age<=#{age} ]]>
=====spring
初识Spring框架
Spring的野心
了解了历史,有个问题值得我们去深思?spring到底想干什么?
它想把全球最好的技术组合到一起为企业提供高质量的企业级的应用程序框架,减轻开发者开发的难度,减少重复的代码。
目标很宏大,那如何下手呢?如果是你,你会怎么实现?第一步要干什么呢?
我们拿经典的框架来举例子。
struts2作为WEB框架深受企业爱戴,它会自己管理action,来创建其实例,这样在程序中就可以访问action的资源。hibernate作为持久层优秀的框架,它也自己管理持久对象。可以看到,各个诸侯都自己管理对象,而要想让它们对象复用,那真是繁琐。前面就有失败者WebService,为了管理不同的开发语言的对象而层层包装转换,辛苦制定的规则,还借着J2EE规范之名,也推广不开。
如何破局呢?要想发号施令其它人听,最好的解决办法就是扼住他们的咽喉。在java的世界里最重要的无疑就是对象的生命周期管理。于是spring以此为切入点,实现自己的统治。宣布所有对象由我来管理,struts2你不再管理对象,由我来管理,你要用从我这拿。hibernate你也不再管理对象,由我来管理,你要用从我这拿。你说管就管吗?这两个征战数年战功赫赫的大将军会听一个初出茅庐乳臭未干野小子的话?他们当然不会听,spring的话可以不听,但他们都要听开发者的。开发一个完整的系统有四个核心,WEB层支持、业务逻辑层、持久层支持、事务支持。而这就是它们的软肋,这就是它们的命门所在,它们只能完成一部分工作,不是一个整体解决方案。而spring并没有抹杀它们,而是依然高官厚禄,承认它们的市场地位,还赠与一个事务管理。一边打压一边拉拢,它们两位看看大势已去,只能俯首称臣。于是兵不血刃,一场变革悄然兴起,一个经典的三层框架诞生SSH (Strut2+Spring+Hibernate)。
故事很传奇,听的人很开心。可spring真就这么简单吗?如果这样想,你就大错特错了。例如:spring怎么来实现对象的管辖?怎么让不同技术之间能简单的互相配合?这才是spring的决胜之处。
为实现这些spring是煞费苦心,创新的形成了一套新的理论体系,可谓前无古人后无来者,并且spring并没有停止不前,这只是统治地球的第一步,随着spring占领市场后,开始对有功之臣进行清洗,struts2不再优秀,致命bug层出不穷,刚好落井下石,spring推出了springmvc,最终终结了struts2。hibernate想用jdbcTemplate和jdo替代,却被mybatis超越,目前还未统一。世界又达到新的平衡,经典的新三大框架诞生,SSM(SpringMVC+Spring+MyBatis)。Spring并没有放弃,而是另辟蹊径,推出新的产品SpringBoot+SpringCloud可以看出spring确实有一统江湖之势!
介绍
Spring 是企业级应用中的一个软件开发框架(Framework),是一个半成品。最大优势是更好的实现了资源的整合(整合mybatis,整合springmvc,整合Redis…)。例如整合JDBC,MyBatis,Hibernate等框架资源以更好的简化应用软件开发,降低软件开发周期。
其中最核心的是:IoC控制反转、DI依赖注入、Bean工厂、SpringAOP面向切面编程、事务控制。
核心架构
Spring 最初的目标就是要整合一切优秀资源,然后对外提供一个统一的服务。Spring 模块构建在核心容器之上,核心容器定义了创建、配置和管理 bean 的方式,如下图所示:
组成 Spring 框架的每个模块(或组件)都可以单独存在,或者与其他一个或多个模块联合实现。每个模块的功能如下:
| 模块 | 说明 | |
|---|---|---|
| 核心容器Spring Core | 核心容器,提供Spring框架的基本功能。核心容器的主要组件是BeanFactory,它是工厂模式的实现。BeanFactory 使用控制反转(IOC)模式,将应用程序的配置和依赖性规范与实际的应用程序代码分开。 | |
| Spring Context | Spring上下文,是一个配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企业服务,例如 JNDI、EJB、电子邮件、国际化、校验和调度功能。 | |
| Spring AOP | 通过配置管理特性,Spring AOP 模块直接将面向切面的编程功能集成到了 Spring 框架中。可以很容易地使 Spring框架管理的任何对象支持AOP。Spring AOP模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,就可以将声明性事务管理集成到应用程序中。 | |
| Spring DAO | JDBC DAO 抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。 | |
| Spring ORM | Spring 框架插入了若干个 ORM 框架,从而提供了 ORM 的对象关系工具,其中包括JDO、Hibernate和iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。 | |
| Spring Web | Web上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。所以Spring 框架支持与 Jakarta Struts的集成。Web模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。 | |
| Spring MVC框架 | MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、Velocity、Tiles、iText 和 POI。 |
Spring 框架的功能可以用在任何J2EE服务器中,大多数功能也适用于不受管理的环境。Spring 的核心要点是:支持不绑定到特定J2EE服务的可重用业务和数据访问对象。毫无疑问,这样的对象可以在不同J2EE环境(Web或EJB)、独立应用程序、测试环境之间重用。
核心组件
| 模块 | 说明 | |
|---|---|---|
| BeanFactory | Spring内部使用,创建bean的工厂 | |
| ApplicationContext | 外部应用程序调用,也成为spring容器的上下文 | |
| IoC控制反转 Inversion of Control |
开发者在无需自己new对象,无需关心对象的创建过程 User user = new User(); 手动创建对象 User user = context.getBean(user); 容器创建对象 |
|
| DI依赖注入 Dependency Injection |
松耦合方式实现对象直接的依赖 | |
| AOP面向切面编程 | 补充java面向对象的不足 |
主要jar组成
| 模块 | 说明 | |
|---|---|---|
| org.springframework.core | 核心工具包,其他包依赖此包 | |
| org.springframework.beans | 核心,包括:配置文件,创建和管理bean等 | |
| org.springframework.aop | 面向切面编程,提供AOP的实现 | |
| org.springframework.context | 提供IoC功能上的扩展服务,此外还提供许多企业级服务的支持,邮件、任务调度、JNDI定位、EJB集成、远程访问、缓存以及多种视图层框架的支持 | |
| org.springframework.web.mvc | 包含SpringMVC应用开发时所需的核心类 | |
| org.springframework.transaction | 为JDBC、Hibernate、JDO、JPA提供一致的声明式和编程式事务管理 | |
| org.springframework.web | 包含Web应用开发时所需支持类 | |
| org.springframework.aspects | 提供对AspectJ框架的支持 | |
| org.springframework.test | 对junit等测试框架的简单封装 | |
| org.springframework.asm | 3.0后提供自己独立的,反编译 | |
| org.springframework.context.support | Context的扩展支持,用于mvc方面 | |
| org.springframework.expression | Spring表达式语言 | |
| org.springframework.instument | 对服务器的代理接口 | |
| org.springframework.jdbc | 对jdbc的简单封装 | |
| org.springframework.jms | 为简化jms api的使用而做的简单封装 | |
| org.springframework.orm | 整合第三方orm,如hibernate/mybatis | |
| org.springframework.web.servlet | 增强servlet |
IoC控制反转
概述
IOC(Inversion of Control),控制反转。
就是指将对象的创建,对象的存储(map),对象的管理(依赖查找,依赖注入)交给了spring容器。
入门案例 - 创建Maven工程


pom.xml
<!-- 集中定义依赖版本号 --><br /> <properties><br /> <junit.version>4.10</junit.version><br /> <spring.version>4.1.3.RELEASE</spring.version><br /> </properties>
<dependencies><br /> <!-- 单元测试 --><br /> <dependency><br /> <groupId>junit</groupId><br /> <artifactId>junit</artifactId><br /> <version>${junit.version}</version><br /> <scope>test</scope><br /> </dependency>
<!-- Spring --><br /> <dependency><br /> <groupId>org.springframework</groupId><br /> <artifactId>spring-webmvc</artifactId><br /> <version>${spring.version}</version><br /> </dependency>
</dependencies><br /></project>
创建Hello.java
applicationContext.xml
在软件应用中由Spring管理的所有对象都称之为Bean对象.我们自己创建的类。假如需要由spring管理,需要对这个类进行配置,常用配置方式有两种:配置文件和注解,先用配置文件:
<?xml version=“1.0” encoding=“UTF-8”?>
xsi:schemaLocation=“http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd“>
<!-- 声明bean对象,<br /> id:唯一标志<br /> class:bean对象的全路径<br /> --><br /> <bean id=_"hi"_ class=_"cn.tedu.spring.Hello"_></bean><br /> <br /></beans>
TestIoC.java
package cn.tedu.test;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import cn.tedu.spring.Hello;
public class TestIoc {
//测试spring管理bean对象<br /> @Test<br /> public void ioc(){<br /> //加载核心配置文件<br /> ClassPathXmlApplicationContext ac=<br /> new ClassPathXmlApplicationContext(<br /> "applicationContext.xml");<br /> <br /> //获取bean对象<br /> //hi是在配置文件中bean对象的id值<br /> Hello h = (Hello) ac.getBean("hi");<br /> <br /> //调用bean对象的方法<br /> h.hi();<br /> }<br /> <br />}
小结
这就是spring框架的IoC,控制反转。之前我们自己new出新类。User u = new User();变成由一个初始化的xml配置文件来创建,也就是由spring容器来创建。遍历xml配置文件,读取到
Bean对象的多实例
概述
在Spring容器中管理的Bean对象的作用域可以通过scope属性或用相关注解指定其作用域,最常用是singleton,prototype。其含义如下:
- singleton:单例,是默认值。这个作用域标识的对象具备全局唯一性。
singleton负责对象的创建、初始化、销毁。
- prototype:多例。这个作用域标识的对象每次获取都会创建新的对象。
applicationContext.xml
<?xml version=“1.0” encoding=“UTF-8”?>
xsi:schemaLocation=“http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd“>
<br /></beans>
TestIoC.java
spring扩展
导入约束自动提示
如果使用代理方式,跳过下面的内容,详细操作访问下面网址:
http://schema.tedu.cn/proxy/
找到jar包中的xsd文件
自定义xsd提示
浏览xsd文件,复制拼接到下面的链接中
关闭xml文件,再次打开,提示出现
面试:IoC和DI
在平时的java应用开发中,我们要实现某一个功能或者说是完成某个业务逻辑时可能需要多个对象来协作完成,在没有使用Spring的时候,每个对象在需要使用他的合作对象时,自己均要使用像new object() 这样的语法来将合作对象创建出来,这个合作对象是由自己主动创建出来的,创建合作对象的主动权在自己手上,自己需要哪个合作对象,就主动去创建,创建合作对象的主动权和创建时机是由自己把控的,而这样就会使得对象间的耦合度高了,A对象需要使用合作对象B来共同完成一件事,A要使用B,那么A就对B产生了依赖,也就是A和B之间存在一种耦合关系,并且是紧密耦合在一起,而使用了Spring之后就不一样了,创建合作对象B的工作是由Spring来做的,Spring创建好B对象,然后存储到一个容器里面,当A对象需要使用B对象时,Spring就从存放对象的那个容器里面取出A要使用的那个B对象,然后交给A对象使用,至于Spring是如何创建那个对象,以及什么时候创建好对象的,A对象不需要关心这些细节问题(你是什么时候生的,怎么生出来的我可不关心,能帮我干活就行),A得到Spring给我们的对象之后,两个人一起协作完成要完成的工作即可。
所以控制反转IoC(Inversion of Control)是说创建对象的控制权进行转移,以前创建对象的主动权和创建时机是由自己把控的,而现在这种权力转移到第三方,比如转移交给了IoC容器,它就是一个专门用来创建对象的工厂,你要什么对象,它就给你什么对象,有了 IoC容器,依赖关系就变了,原先的依赖关系就没了,它们都依赖IoC容器了,通过IoC容器来建立它们之间的关系。
DI(依赖注入)其实就是IOC的另外一种说法,DI是由Martin Fowler 在2004年初的一篇论文中首次提出的。他总结:控制的什么被反转了?就是:获得依赖对象的方式反转了。
IoC是设计思想,IoC有三个核心:BeanFactory、反射、DI。BeanFactory利用反射实现对象的创建,DI实现对象关系管理。


