分层解耦
类聚
-
软件中各个功能模块内部的功能联系.
-
例如:
-
高类聚示例:想象一下餐厅的厨房,每个厨师负责自己的工作站,一个专门做沙拉,一个专门烤肉,另一个专门做甜点。每个工作站内的工作高度类聚,即每个厨师只专注于自己的领域,不参与其他工作站的任务。在软件中,如果Controller层只负责接收请求和发送响应,不执行任何业务逻辑或数据处理,那么这就体现了高类聚性。
-
低类聚示例:在同一个厨房中,如果每个厨师都要参与制作所有的菜品,那么工作站的类聚性就很低。在软件中,如果Controller层不仅要处理请求和响应,还要处理数据库操作、业务逻辑验证等,那么它就违反了高类聚的原则。
-
耦合
-
衡量软件中各个层/模块的依赖关系.关联程度
-
例如:
-
低耦合示例:想象一下乐高积木,每个积木块都是独立的,可以轻松地与其他积木块组合或分离,而不影响其他块。在软件中,如果Service层只通过定义良好的接口与DAO层交互,而不直接访问DAO层的内部实现细节,那么这就体现了低耦合性。
-
高耦合示例:在软件中,如果Service层直接访问和操作数据库,或者Controller层直接与数据库交互,而不是通过Service层或DAO层,那么这就形成了高耦合。这种情况下,任何对数据库结构的修改都可能影响到Service层或Controller层的代码,使得系统难以维护和扩展。
-
三层架构实例说明
-
比起不用三层架构,原来方法,低类聚,高耦合.将所有操作写在Controller层,复用性差,维护性差
-
使用三层架构后,类聚性明显提高,高耦合性降低.但是还是有耦合
###
IOC & DI入门
简介
-
IOC(Inversion of Control,控制反转)将对象的创建权由程序自身转移到外部(容器),这种思想称为控制反转
-
DI(Dependency Injection,依赖注入)是IOC的一种实现方式。依赖注入指的是在运行时,由外部容器动态地将依赖关系注入到对象中。
-
Bean对象:IOC容器中创建,管理的对象,称作Bean
Bean的注解(IOC)
类型 | 注解 | 说明 | 使用位置 | 备注 |
---|---|---|---|---|
基础注解 | @Component | 声明bean的基础注解,用于非控制器、非业务逻辑、非数据访问类 | 通用类 | 最广泛使用的注解 |
控制器层级 | @Controller | 组件的衍生注解,用于标注Spring MVC中的控制器类 | 控制器类 | 处理HTTP请求 |
业务层级 | @Service | 组件的衍生注解,用于标注业务逻辑类 | 业务类 | 封装业务逻辑 |
数据访问层级 | @Repository | 组件的衍生注解,用于标注数据访问对象,如DAO | 数据访问类 | 通常与ORM框架整合使用 |
@Component
-
通过spring的@Component类注解将,某个实现类,交给IOC容器管理
@Component //将EmpDaoA交给spring容器管理
public class EmpDaoA implements EmpDao {@Overridepublic List<Emp> listEmp() {//调用工具类解析xml文件String file = this.getClass().getClassLoader().getResource("emp.xml").getFile();//System.out.println(file);List<Emp> emps = XmlParserUtils.parse(file, Emp.class);return emps;}
}
注意事项:
-
声明bean时,可以通过
value
属性指定bean的名字,如果未指定,则默认使用类名的首字母小写形式作为bean的名称。 -
在Spring Boot集成Web开发中,声明控制器bean时,只能使用
@Controller
注解,而不能使用其他注解。
DI(依赖注入)
@Autowired
-
默认按照类型自动装配
-
属性注入: 属性注入是最简单的方式,它允许你通过将
@Autowired
注解放在类的属性上来注入依赖。Spring 容器会自动查找合适的 Bean 并将其赋值给该属性。这种方式简单直观,但是它不支持不可变的对象(因为需要在构造器之外设置属性)。@Autowired private MyDependency myDependency;
-
构造器注入: 构造器注入要求你提供一个带有参数的构造器,并在构造器上使用
@Autowired
注解。Spring 容器会自动调用这个构造器,并将所需的依赖作为参数传递给它。这种方式推荐用于必须的依赖,因为它可以保证在对象创建时就提供了所有必需的依赖,而且支持不可变对象。@Autowired public MyService(MyDependency myDependency) {this.myDependency = myDependency; }
-
方法注入: 方法注入是一种更灵活的注入方式,它允许你在类的任意方法上使用
@Autowired
注解。Spring 容器会在创建 Bean 后调用标记了@Autowired
的方法,并将所需的依赖作为参数传递。这种方式不常用于设置属性,而是用于初始化操作或配置方法。@Autowired public void setMyDependency(MyDependency myDependency) {this.myDependency = myDependency; }
多个同类型的Bean
-
@Primary
-
类注解,将它加在某个类上,这是如果遇到相同的类型时会以它为准.
-
//这时如果冲突会以ServiceA为准
@Primary
@Service
public class ServiceA implements EmPS{......}
//
@Service
public class ServiceB implements EmPS{......}
-
@Autowired +@Qualifier("bean的名称")
@RestController
public class EmpController{@Autowired@Qualifier("ServiceB")EmPS emps;//......
}
-
@Resource(name = "bean的名称")
@RestController
public class EmpController{@Resource("ServiceB")EmPS emps;//......
}
-
@Resource 和 @Autowired 区别
-
@Autowired是spring框架提供的注解,而@Resource是JDK提供的注解
-
@Autowired默认按照类型注入,@Resource默认按照名称注入
-
Bean组件扫描
介绍
-
组件扫描的必要性:要使
@Component
、@Controller
、@Service
、@Repository
等注解生效,需要通过组件扫描注解@ComponentScan
来实现。 -
@ComponentScan
注解:-
通常不需要显式配置
@ComponentScan
。 -
在Spring Boot应用中,
@SpringBootApplication
注解已经包含了**@ComponentScan**
。
-
-
默认扫描范围:
@ComponentScan
默认扫描启动类所在的包以及其子包。
使用
-
显式指定扫描的包: 如果你希望Spring容器只扫描特定的包,可以在启动类或配置类上使用
@ComponentScan
并指定包路径。@ComponentScan("com.itheima.controller") // 只扫描com.itheima.controller包
-
使用通配符扫描多个包: 如果你想要扫描多个包,可以使用通配符。
@ComponentScan("com.itheima.*") // 扫描com.itheima下的所有包
-
扫描多个具体的包: 如果你有多个包需要扫描,可以传递一个包路径数组。
@ComponentScan({"com.itheima.controller","com.itheima.service" })
注意
-
使用它会覆盖@SpringBootApplication的默认扫描.