IoC控制反转:
- 控制反转IoC(Inversion of Control)是一种思想。指将传统上由程序代码直接操控的对象调用权交给容器,通过容器来实现对象的装配和管理。控制反转就是对对象控制权的转移,从程序代码本身反转到了外部容器。通过容器实现对象的创建,属性赋值, 依赖的管理。
- 当前比较流行的实现方式是依赖注入。(Spring框架使用依赖注入DI实现 IoC)
- 依赖: classA 类中含有 classB 的实例,在 classA 中调用 classB 的方法完成功能,即 classA对 classB 有依赖。
- 依赖注入: DI(Dependency Injection),依赖注入 DI 是指程序运行过程中,若需要调用另一个对象协助时,无须在代码中创建被调用者,而是依赖于外部容器,由外部容器创建后传递给程序。
一、三层架构下Spring项目结构:
- 项目结构:
- Spring核心配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--这里面编写核心配置-->
</beans>
- 表示层:
UsersController类:见(二)、(三)、(四)。
- 业务逻辑层:
UsersService接口:
package org.example.service;
public interface UsersService {
void service();
}
UsersServiceImpl实现类:见(二)、(三)、(四)。
- 数据访问层:
UsersMapper接口:
package org.example.dao;
public interface UsersMapper {
int insert();
}
UsersMapperImpl实现类:见(二)、(三)、(四)。
二、控制正转:传统用户操作对象
- 项目基础结构同(一)。
- UsersMapperImpl实现类:
package org.example.dao;
/**
* 数据访问层
*/
public class UsersMapperImpl implements UsersMapper{
@Override
public int insert() {
System.out.println("用户增加成功");
return 1;
}
}
- UsersServiceImpl实现类:
package org.example.service;
import org.example.dao.UsersMapper;
import org.example.dao.UsersMapperImpl;
/**
* 业务逻辑层
*/
public class UsersServiceImpl implements UsersService{
//业务逻辑层必须要有数据访问层对象
UsersMapper usersMapper;//面向接口编程
//带参构造方法
public UsersServiceImpl(UsersMapper usersMapper) {
this.usersMapper = usersMapper;
}
//业务逻辑层具体功能
@Override
public void service() {
usersMapper.insert();
}
}
- UsersController类:
package org.example.controller;
import org.example.service.UsersService;
import org.example.service.UsersServiceImpl;
/**
* 表示层
*/
public class UsersController {
//表示层中必须要有业务逻辑层对象
UsersService usersService;
//带参构造方法
public UsersController(UsersService usersService) {
this.usersService = usersService;
}
//表示层具体功能
public void control(){
usersService.service();
}
}
- 测试类:
@Test
public void aTest() {
//手动创建数据访问层对象
UsersMapper usersMapper = new UsersMapperImpl();
//手动创建业务逻辑层对象,并通过构造方法把数据访问层对象传给业务逻辑层对象
UsersService usersService = new UsersServiceImpl(usersMapper);
//手动创建表示层对象,并通过构造方法把业务逻辑层对象传给表示层对象
UsersController usersController = new UsersController(usersService);
//调用表示层对象的方法
usersController.control();
}
- 控制正转缺点:
我们在使用某些对象时需要手动new对象,然后通过构造方法或set方法手动传值,程序繁琐,不具有复用性。
三、Spring基于XML的IoC:
- 项目基础结构同(一)。
- UsersMapperImpl实现类:
package org.example.dao;
/**
* 数据访问层
*/
public class UsersMapperImpl implements UsersMapper{
@Override
public int insert() {
System.out.println("用户增加成功");
return 1;
}
}
- UsersServiceImpl实现类:
package org.example.service;
import org.example.dao.UsersMapper;
import org.example.dao.UsersMapperImpl;
/**
* 业务逻辑层
*/
public class UsersServiceImpl implements UsersService{
//业务逻辑层必须要有数据访问层对象
UsersMapper usersMapper;//面向接口编程
//set方法
public void setUsersMapper(UsersMapper usersMapper) {
this.usersMapper = usersMapper;
}
//无参构造方法
public UsersServiceImpl() {
}
//带参构造方法
public UsersServiceImpl(UsersMapper usersMapper) {
this.usersMapper = usersMapper;
}
//业务逻辑层具体功能
@Override
public void service() {
usersMapper.insert();
}
}
- UsersController类:
package org.example.controller;
import org.example.service.UsersService;
import org.example.service.UsersServiceImpl;
/**
* 表示层
*/
public class UsersController {
//表示层中必须要有业务逻辑层对象
UsersService usersService;
//set方法
public void setUsersService(UsersService usersService) {
this.usersService = usersService;
}
//无参构造方法
public UsersController() {
}
//带参构造方法
public UsersController(UsersService usersService) {
this.usersService = usersService;
}
//表示层具体功能
public void control(){
usersService.service();
}
}
- Spring核心配置文件:
<?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标签:一个bean标签代表创建了一个对象
参数说明:
id:创建对象的名称
class:对象所属的类,这里只能是类,不能是接口
-->
<!--property标签:通过对象的set方法给对象的属性赋值,也叫setter注入
使用前提:对象必须有无参构造方法和set方法
参数说明:
name:对象中属性名称
value:基本数据类型赋属性值
ref:引用数据类型赋属性值
-->
<!--constructor-arg标签:通过对象的构造方法给对象的属性赋值,也叫构造方法注入
使用前提:对象必须有带参构造方法
参数说明:
name:构造方法中局部变量的名称
index:构造方法中局部变量的位置
value:基本数据类型赋属性值
ref:引用数据类型赋属性值
-->
<!--创建数据访问层对象-->
<bean id="UsersMapperImpl" class="org.example.dao.UsersMapperImpl">
</bean>
<!--创建业务逻辑层对象-->
<bean id="UsersServiceImpl" class="org.example.service.UsersServiceImpl">
<!--依赖注入-->
<property name="usersMapper" ref="UsersMapperImpl"></property>
</bean>
<!--创建表示层对象-->
<bean id="UsersController" class="org.example.controller.UsersController">
<!--依赖注入-->
<property name="usersService" ref="UsersServiceImpl"></property>
</bean>
</beans>
- 测试类:
@Test
public void bTest(){
/**
* ApplicationContext容器,会在容器对象初始化时,通过调用各对象的无参构造方法将其中的所有对象一次性全部创建完成。
* 以后代码中若要使用到这些对象,只需从内存中直接获取即可。执行效率较高。但占用内存。
* Spring初始化对象时要使用无参的构造方法,切记保证类中有无参构造方法。
*/
//创建容器对象并启动
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//根据对象name名称取出对象,注意是取,不是创建
UsersController usersController = (UsersController) ac.getBean("UsersController");
usersController.control();
}
四、Spring基于注解的IoC:
- 创建对象的注解:
@Component
:可创建所有类型的对象都可以使用此注解,默认名称是类名的驼峰命名法.也可以指定对象的名称@Component(“指定名称”)。@Controller
:可创建表示层的对象,此对象可以接收用户请求,返回处理结果给客户端。@Service
:可创建业务逻辑层的对象,此对象可施事务控制,向上给表示层返回数据,向下调用数据访问层。@Repository
:可创建数据访问层的对象 ,对数据库中的数据进行增删改查操作。
- 给属性赋值(依赖注入)的注解:
@Value
:给基本数据类型注入值。@Autowired
:给引用数据类型按类型注入,从整个Bean工厂中搜索同源类型的对象进行注入。@Qualifier
:给引用数据类型按名称注入,从整个Bean工厂中搜索相同名称的对象进行注入。@Resource(name = "userDao")
:按名称注入。
- 项目基础结构同(一)。
- UsersMapperImpl实现类:
package org.example.dao;
import org.springframework.stereotype.Repository;
/**
* 数据访问层
*/
@Repository//数据访问层注解
public class UsersMapperImpl implements UsersMapper{
@Override
public int insert() {
System.out.println("用户增加成功");
return 1;
}
}
- UsersServiceImpl实现类:
package org.example.service;
import org.example.dao.UsersMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* 业务逻辑层
*/
@Service
public class UsersServiceImpl implements UsersService{
//业务逻辑层必须要有数据访问层对象
@Autowired//业务逻辑层注解
UsersMapper usersMapper;//面向接口编程
@Override
public void service() {
usersMapper.insert();
}
//不再需要带参构造方法和set方法
}
- UsersController类:
package org.example.controller;
import org.example.service.UsersService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
/**
* 表示层
*/
@Controller
public class UsersController {
//表示层中必须要有业务逻辑层对象
@Autowired//表示层注解
UsersService usersService;
//表示层具体功能
public void control(){
usersService.service();
}
//不再需要带参构造方法和set方法
}
- Spring核心配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!--添加包扫描,通过扫描包内的注解创建对象-->
<context:component-scan base-package="org.example.controller"></context:component-scan>
<context:component-scan base-package="org.example.service"></context:component-scan>
<context:component-scan base-package="org.example.dao"></context:component-scan>
</beans>
- 测试类:
@Test
public void cTest(){
/**
* ApplicationContext容器,会在容器对象初始化时,通过调用各对象的无参构造方法将其中的所有对象一次性全部创建完成。
* 以后代码中若要使用到这些对象,只需从内存中直接获取即可。执行效率较高。但占用内存。
* Spring初始化对象时要使用无参的构造方法,切记保证类中有无参构造方法。
*/
//创建容器对象并启动
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//根据对象name名称取出对象,注意是取,不是创建
UsersController usersController = (UsersController) ac.getBean("usersController");
usersController.control();
}