1.分层耦合介绍
- 对一个系统进行分层处理,就是为了将一个系统按其功能的最终呈现而进行职责的分离,不同的层次进行不同职责的功能划分
- 通常我们在做J2EE项目的技术架构时,通常会考虑一种分层的模型:
目前非常流行的分层做法是控制层一般采用struts,springmvc,在业务层采用spring,EJB,在持久层采用hibernate,ibatis,jdbcTemplate等。
2.三层架构:
- controller:控制层,接收前端发送的请求,对请求进行处理,并响应数据。
- service:业务逻辑层,处理具体的业务逻辑。
- dao:数据访问层(Data Access Object)(持久层),负责数据访问操作,包括数据的增、删、改、查。
3.分层解耦思想
- 内聚:软件中各个功能模块内部的功能联系。
- 耦合:衡量软件中各个层/模块之间的依赖、关联的程度。
- 软件设计原则:高内聚,低耦合。
解耦相关:
- 控制反转:Inversion Of Control,简称IOC。对象的创建控制权由程序自身转移到外部(容器),这种思想称为控制反转.
- 依赖注入:Dependency Injection,简称DI。容器为应用程序提供运行时,所依赖的资源称之为依赖注入。
- Bean对象:IOC容器中创建、管理的对象,称之为bean。
4.IOC & DI 入门
- Service层及Dao层的实现类,交给IOC容器管理。(加入
@Component
注解)
Dao层:
@Component //加入此注解表示将当前类交给IOC容器管理,成为IOC容器中的Bean --控制反转
public class EmpDaoA implements EmpDao {
public List<Emp> listEmp() {
//1.从文件中查询数据
String file = this.getClass().getClassLoader().getResource("emp.xml").getFile();
List<Emp> empList = XmlParserUtils.parse(file, Emp.class)
return empList;
}
}
service层:
@Component //加入此注解表示将当前类交给IOC容器管理,成为IOC容器中的Bean --控制反转
public class EmpServiceA implements EmpService {
private EmpDao empDao;
public List<Emp> listEmp() {
//调用dao层,查询数据
List<Emp> empList = empDao.listEmp();
//.....
- 为Controller及Service注入运行时,依赖的对象。(加入
@Autowired
注解)
Controller层:
@RestController
public class EmpController {
@Autowired //运行时,IOC容器会提供该类型的bean对象,并将其赋值给变量 --依赖注入
private EmpService empService;
@RequestMapping("/listEmp")
public Result listEmp() throws Exception {
List<Emp> empList = empService.listEmp();
return Result.success(empList);
}
}
Services层:
@Component //加入此注解表示将当前类交给IOC容器管理,成为IOC容器中的Bean --控制反转
public class EmpServiceA implements EmpService {
@Autowired 运行时,IOC容器会提供该类型的bean对象,并将其赋值给变量 --依赖注入
private EmpDao empDao;
public List<Emp> listEmp() {
//调用dao层,查询数据
List<Emp> empList = empDao.listEmp();
// ......
}
- 运行测试。
5. IOC详解
1.bean的声明
要把某个对象交给IOC容器管理,需要在对应的类上加上如下注解之一:
注解 | 说明 | 位置 |
---|---|---|
@Component |
声明bean 的基础注解 |
不属于以下三类时用此注解 |
@Controller |
@Component 的衍生注解 |
标注在控制器类上 |
@Service |
@Component 的衍生注解 |
标注在业务类上 |
@Repository |
@Component 的衍生注解 |
标注在数据访问类上(由于与mybatis 整合,用的少) |
注意事项:
-
- 声明
bean
的时候,可以通过value
属性指定bean
的名字,如果没有指定,默认为类名首字母小写。
- 声明
-
- 使用以上四个注解都可以声明
bean
,但是在springboot
集成web开发中,声明控制器bean只能用@Controller
。
- 使用以上四个注解都可以声明
2.bean的组件扫描
- 前面声明
bean
的四大注解,要想生效,还需要被组件扫描注解@ComponentScan
扫描。 @ComponentScan
注解虽然没有显式配置,但是实际上已经包含在了启动类声明注解@SpringBootApplication
中,默认扫描的范围是启动类所在包及其子包。
6.DI详解
1.bean的注入
- @Autowired注解,默认是按照类型进行,如果存在多个相同类型的bean,将会报出如下错误:
Description:
Field empService in com.mannor.dao.Controller.EmpController required a single bean, but 2 were found:
- empServiceA: defined in file [D:\Code\web-front-end\mannor_web_project\springboot-web-resp-req\target\classes\com\mannor\service\Impl\EmpServiceA.class]
- empServiceB: defined in file [D:\Code\web-front-end\mannor_web_project\springboot-web-resp-req\target\classes\com\mannor\service\Impl\EmpServiceB.class]
Action:
Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed
- 通过以下几种方案来解决:
- @Primary:
@Primary //设置的是bean的优先级
@Service
public class EmpServiceA implements EmpService {
}
- @Autowired+@Qualifier:
@RestController
public class EmpController {
@Autowired
@Qualifier("empServiceA") //后面跟的参数是bean的名称(默认为类名首字母小写)
private EmpService empService;
}
- @Resource:
@RestController
public class EmpController {
//把@Autowired
@Resource(name = "empServiceB") //后面跟的参数是bean的名称(默认为类名首字母小写)
private EmpService empservice ;
}
@Resource
与@Autowired
区别(面试题)
@Autowired
是spring框架提供的注解,而@Resource
是JDK提供的注解。@Autowired
默认是按照类型注入,而@Resource
默认是按照名称注入。