首先在说IOC之前先来说说IOC对于Spring的重要地位,Spring发展到现在,IOC真的是功不可没。
什么是IOC?(控制反转):
是一种设计思想,IOC即控制反转,意思是对象的创建不通过 手动 new,而是把对象的创建权交给Spring容器来完成。
有人认为IOC也称为DI但是我不这么认为,我认为DI(依赖注入)是IOC的一种方式,咱们这篇文章主要来谈关于IOC,具体DI的讲解,咱们放在下一篇。
在认识到IOC之前,对于我来说“面向对象”编程的思想充满了我的脑海,一需要什么东西,我的第一反应就是“new一个”
这是我们通常的做事方式,需要什么就通过 new 对象的方式去创建,这种情况导致,对象和它所依赖的对象耦合在一起,
其实我们需要思考一个问题?我们每次用到自己依赖的对象真的需要自己去创建吗?我们知道,我们依赖对象其实并不是依赖该对象本身,而是依赖它所提供的服务,只要在我们需要它的时候,它能够及时提供服务即可,至于它是我们主动去创建的还是别人送给我们的,其实并不是那么重要。
这个给我们送东西的“人” 就是 IoC,在上面的例子中,它就相当于一个婚介公司,作为一个婚介公司它管理着很多男男女女的资料,当我们需要一个女朋友的时候,直接跟婚介公司提出我们的需求,婚介公司则会根据我们的需求提供一个妹子给我们,我们只需要负责谈恋爱,生猴子就行了。你看,这样是不是很简单明了。
下面我就通过一个例子来讲解:
- 先在持久层(Dao)层建立三个不同的类
//UserDao接口:
package com.kuang.Dao;
public interface UserDao {
void getUser();
}
//UserDaoImpl实现类
package com.kuang.Dao;
public class UserDaoImpl implements UserDao{
public void getUser(){
System.out.println("默认获取信息方式");
}
}
//UserDaoMysqlImpl实现类
package com.kuang.Dao;
public class UserDaoMysqlImpl implements UserDao {
public void getUser(){
System.out.println("赫于富的MySql");
}
}
//UserDaoSqlServerImpl实现类
package com.kuang.Dao;
public class UserDaoSqlServerImpl implements UserDao{
public void getUser(){
System.out.println("赫于富的SqlServer");
}
}
- 业务层:
//接口
package com.kuang.service;
public interface UserService {
void getUser();
}
如果在没有IOC之前我们面向对象的业务实现会这样写:-------------------------------------------------------------------------
package com.kuang.service;
import com.kuang.Dao.UserDao;
import com.kuang.Dao.UserDaoMysqlImpl;
public class UserServiceImpl implements UserService{
//添加了类之后修改了原来的代码,这里原来是UserDaoImpl
UserDao userDao=new UserDaoMysqlImpl();
public void getUser(){
userDao.getUser();
}
}
测试类:
import com.kuang.service.UserService;
import com.kuang.service.UserServiceImpl;
public class MyTest {
public static void main(String[] args){
//用户实际调用的是业务层,dao层他们不需要调用
UserService userService=new UserServiceImpl();
userService.getUser();
}
}
结果:
这种方式就是面向对象的设计思想,弊端就是当我们不再需要MySql的时候我们就需要去更改代码
每一次用户提交了新的请求,我们程序员都需要根据用户的需求去改代码,这一定不是一个好的程序
-------------------------------------------------------------------------------------------------------------------------------------------------------------
加入IOC之后:
业务层的实现类发生了变化:
package com.kuang.service;
import com.kuang.Dao.UserDao;
public class UserServiceImpl implements UserService{
//添加了类之后修改了原来的代码,这里原来是UserDaoImpl
// UserDao userDao=new UserDaoMysqlImpl();
//使用IOC的
private UserDao userDao;
public void setUserDao(UserDao userDao){
this.userDao=userDao;
}
public void getUser(){
userDao.getUser();
}
}
测试类也改变:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.kuang.service.UserServiceImpl;
public class MyTest {
public static void main(String[] args){
//用户实际调用的是业务层,dao层他们不需要调用
//获取ApplicationContext 拿到Spring容器
ApplicationContext context =new ClassPathXmlApplicationContext("Bean.xml");
//容器在手天下我有,需要什么就直接get什么
UserServiceImpl userServiceImpl=(UserServiceImpl)
context.getBean("UserServiceImpl");
userServiceImpl.getUser();
}
}
在使用Spring IOC的时候我们多了一个Bean.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">
<bean id="mysqlImpl" class="com.kuang.Dao.UserDaoMysqlImpl"/>
<bean id="sqlserverImpl" class="com.kuang.Dao.UserDaoSqlServerImpl"></bean>
<!--id 是bean的唯一标识符,也就是相当于我们学的对象名
class: 相当于bean对象所对应的全闲
-->
<bean id="UserServiceImpl" class="com.kuang.service.UserServiceImpl" name="user2 u2">
<!--ref: 引用spring容器中创建好的对象
value:具体的值,基本数据类型
name: 也是别名 , 而且name可以同时取多个别名
-->
<property name="userDao" ref="sqlserverImpl"></property>
</bean>
<!-- 别名 如果添加了别名,我们也可以使用别名获取到对象-->
<alias name="UserServiceImpl" alias="123"></alias>
</beans>
执行结果:
最后我们如果想要更改需求,只需要通过修改Bean.xml配置文件即可
假如我把 “sqlserverImpl”改为“mysqlImpl”
其他的代码不进行修改,再次看执行结果:发生了变化!!!1
总结:
- 谁控制谁:在传统的开发模式下,我们都是采用直接 new 一个对象的方式来创建对象,也就是说你依赖的对象直接由你自己控制,但是有了 IOC 容器后,则直接由 IoC 容器来控制。所以“谁控制谁”,当然是 IoC 容器控制对象。
- 控制什么:控制对象。
- 为何是反转:没有 IoC 的时候我们都是在自己对象中主动去创建被依赖的对象,这是正转。但是有了 IoC 后,所依赖的对象直接由 IoC 容器创建后注入到被注入的对象中,依赖的对象由原来的主动获取变成被动接受,所以是反转。
- 哪些方面反转了:所依赖对象的获取被反转了。