文章目录
2、 IOC推导
-
目的:解决企业应用开发的复杂性
-
功能:使用基本的JavaBean代替EJB,并提供了更多的企业应用功能
-
范围:任何Java应用
Spring是一个轻量级**控制反转(IoC)和面向切面(AOP)**的容器框架。
2.1、 分析实现
我们使用原来的方式写一段代码测试:dao–service—前端
思考:现在前端传递或者调用不会变,所有操作都是我们程序猿来实现;
解决方案:前端操作,后台不变;留一个调用的接口
IOC的原型。
2.2、案例
- 新建一个空白的maven项目,删除src包,将这个Maven工程当做父工程! po在主pom.xml中导入spring所需要的依赖,【最好在右面的maven窗口查看导入包情况,不要出现灰暗的包,灰暗的包都是导入失败的包】
新建立一个Moudle:spring-01-ioc1
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.9.RELEASE</version>
</dependency>
</dependencies>
- 在java包下建包com.westos.dao,在dao层
- 先写一个UserDao接口
public interface UserDao {
public void getUser();
}
- 再去写Dao的实现类
1 public class UserDaoImpl implements UserDao {
2 @Override
3 public void getUser() {
4 System.out.println("获取用户数据");
5 }
6 }
- 在和dao包同级建service包,在service层
- 去写UserService的接口
1 public interface UserService {
2 public void getUser();
3 }
- 再写Service的实现类
1 public class UserServiceImpl implements UserService {
2 private UserDao userDao;
3 UserDao userDao = new UserDaoImpl();
4 @Override
5 public void getUser() {
6 userDao.getUser();
7 }
8 }
- 在测试test包下写一个测试类, 测试一下
1 @Test
2 public void test(){
3 UserService service = new UserServiceImpl();
4 service.getUser();
5 }
- 这是我们原来的方式 , 现在修改一下 .在Dao层把Userdao的实现类增加一个 .
1 public class UserDaoMySqlImpl implements UserDao {
2 @Override
3 public void getUser() {
4 System.out.println("MySql获取用户数据");
5 }
6 }
- 紧接着我们要去使用MySql的话 , 我们就需要去service实现类里面修改对应的实现 .
1 public class UserServiceImpl implements UserService {
2 private UserDao userDao = new UserDaoMySqlImpl();
3
4 @Override
5 public void getUser() {
6 userDao.getUser();
7 }
8 }
- 再假设, 我们再增加一个Userdao的实现类 .
1 public class UserDaoOracleImpl implements UserDao {
2 @Override
3 public void getUser() {
4 System.out.println("Oracle获取用户数据");
5 }
6 }
那么我们要使用Oracle , 又需要去service实现类里面修改对应的实现 . 假设我们的这种需求非常大 , 这种方式就根本不适用了, 甚至反人类对吧 , 每次变动 , 都需要修改大量代码 . 这种设计的耦合性太高了, 牵一发而动全身 .
那我们如何去解决呢 ?
我们可以在需要用到他的地方 , 不去实现它 , 而是留出一个接口 , 利用set , 我们去代码里修改下 .
1 public class UserServiceImpl implements UserService {
//这个方法具有承上启下的作用
//在service层留一个接口
//封装:属性私有,设置public方法操作
2 private UserDao userDao;
3 // 利用set实现
//设置一个接口
4 public void setUserDao(UserDao userDao) {
5 this.userDao = userDao;
6 }
7
8 @Override
9 public void getUser() {
10 userDao.getUser();
11 }
12 }
现在去我们的测试类里 , 进行测试 ;
1 @Test
2 public void test(){
3 UserServiceImpl service = new UserServiceImpl();
4 service.setUserDao( new UserDaoMySqlImpl() );
5 service.getUser();
6 //那我们现在又想用Oracle去实现呢
7 service.setUserDao( new UserDaoOracleImpl() );
8 service.getUser();
9 }
以前所有东西都是由程序去进行控制创建 , 而现在是由我们自行控制创建对象 , 把主动权交给了调用者
. 程序不用去管怎么创建,怎么实现了 . 它只负责提供一个接口 .
即是可以通过前端用户传入的数据调用service层到的方法,再由service层的接口实现的方法去调用dao层方法。只需要通过前端输入即可,dao层和service层都不需要修改,只需要service层留下接口
这种思想 , 从本质上解决了问题 , 我们程序员不再去管理对象的创建了 , 更多的去关注业务的实现 . 耦合性大大降低 . 这也就是IOC的原型 !
2.3、 IOC的本质
控制反转IoC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IoC的一种方法,也有人认为DI只是IoC的另一种说法。没有IoC的程序中 , 我们使用面向对象编程 , 对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了。
IoC是一种思想,在此之前程序中使用对象的创建都必须由程序员完成,IoC将对象的创建,保存,以及管理(生命周期)交由Spring来完成,所以Spring也相当于一个容器(存放对象的对象),该过程即为控制反转。
作用:实现了对象间的解耦,大大降低了耦合性,使模块独立
控制反转 (inversion of Control):IOC
他是一种设计思想。 根据这个思想有实现的方式,DI : 依赖注入。
反转: 从被动到主动 , 程序猿主动控制 到 被动接受 , 由编写代码,编写接口,程序具有高度配置性和动态性;
让程序的耦合性大大降低。方便模块独立,到后来发展为: 微服务。解耦 。
采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。
控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI)。
- 之前,程序是主动创建对象!控制权在程序员手中!
- 使用set注入后,程序不再具有主动性,而是变成了被动的接受对象!
这种思想,从本质上解决了问题,我们程序员不用再去管理对象的创建了。系统的耦合性大大降低,可以更加专注的在业务的实现上!这是IOC的原型
3、第一个程序 :HelloSpring
建立一个Moudle:springmvc-02-hellospring
1.导入jar包
要导入的包在maven中的寻找
在Maven官网上找到要导入的包:百度搜索 Maven打开第一个
可以在此页面中下翻寻找想要导入的包【最好是使用次数最多的包】,此处导入4.3.9.RELEASE包
这段代码就是要导入包的.xml代码
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.9.RELEASE</version>
</dependency>
2.编写一个Hello实体类
package com.westos.pojo;
public class Hello {
private String name;
public Hello() {
}
public Hello(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void show(){
System.out.println("Hello,"+name);
}
@Override
public String toString() {
return "Hello{" +
"name='" + name + '\'' +
'}';
}
}
3.编写我们的spring文件 , 这里我们命名为beans.xml
beans.xml文件的寻找:
地址:https://docs.spring.io/spring/docs/4.3.9.RELEASE/spring-framework-reference/htmlsingle/
翻译的中文文档:https://docs.spring.io/spring/docs/5.2.2.RELEASE/spring-framework-reference/core.html#beans-introduction
在此页面中下翻寻找
或者在翻译的中文文档中寻找:
beans.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就是一个java的的对象,有spring管理和创建-->
<bean id="hello" class="com.westos.pojo.Hello">
<property name="name" value="Spring"/>
</bean>
<!--bean 就是一个java对象,由Spring管理和创建-->
<bean id="hello2" class="com.westos.pojo.Hello">
<property name="name" value="WestOS"/>
</bean>
</beans>
4.测试类
package com.westos.pojo;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class HelloTest {
@Test
public void test(){
//解析beans.xml配置文件,生产管理相应的Bean对象
//ClassPathXmlApplicationContext获得Spring中定义的Bean实例(对象)
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//getBean : 参数即为spring配置文件中bean的id .
//通过Bean得到这个对象的实体
Hello hello = (Hello) context.getBean("hello");
hello.show();
}
}
测试结果
思考问题?
Hello对象是由谁创建的?
- hello对象是由Spring创建的。
- beans.xml ----> 管理bean,Java对象 , Spring就像一个容器,存放了许多的对象;
- 解析配置文件
- 通过反射创建对象并且设置值
- Hello对象的属性是怎么设置值的?
- hello对象的属性是由Spring容器创建的。
这个过程就叫控制反转:IOC
控制:谁来控制对象的创建? 原来 :程序猿来控制, 使用Spring后,Spring来创建对象的
反转:程序本身不创建对象了,变成被动接受对象。
依赖注入:DI ,本质就是利用set方式来注入的。
IOC是一种编程思想。由主动的编程到被动的接受;
可以通过newClassPathXmlApplicationContext去浏览一下底层源码 .
5. 修改测试Demo
使用spring完成之前 Oracle 和 Mysql 获取用户信息的小Demo;
beans.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="UserDaoImpl" class="com.westos.dao.UserDaoImpl"/>
<bean id="UserDaoMysqlImpl" class="com.westos.dao.UserDaoMysqlImpl"/>
<bean id="UserDaoOracleImpl" class="com.westos.dao.UserDaoOracleDao"/>
<bean id="ServiceImpl" class="com.westos.service.UserServiceImpl">
<!--注意: 这里的name并不是属性 , 而是set方法后面的那部分 , 首字母小写-->
<!--引用另外一个bean , 不是用value 而是用 ref-->
<!--普通的值使用value,引用其他bean使用ref-->
<property name="userDao" ref="UserDaoMysqlImpl"/>
</bean>
</beans>
【注意】:
- ref:引用Spring容器中创建好的对象
- value:具体的值,基本数据类型
测试类
package com.westos.test;
import com.westos.service.UserServiceImpl;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringTest {
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
UserServiceImpl userService = (UserServiceImpl) context.getBean("ServiceImpl");
userService.getUser();
}
}
OK , 到了现在 , 我们彻底不用再程序中去改动了 , 要实现不同的操作 , 只需要在xml配置文件中进行修改 , 所谓的IoC,一句话搞定 : 对象由Spring 来创建 , 管理 , 装配 !