springboot三层架构和IOC-DI
1.什么是三层架构
- Controlle:
控制层,负责接收来自前端的请求,处理请求并确定使用哪个服务来执行相应的操作,并响应数据。
- Service:
服务层,服务层通常会被控制器调用来执行特定的任务或操作,保持了业务逻辑的独立性,增加了代码的可重用性和可测试性。
- Dao:
全称Data Access Object,负责数据访问操作,包括数据的增、删、改、查,它封装了对数据的访问和操作,使得服务层可以通过DAO来获取和持久化数据,而无需关注具体的数据存储和操作细节。
2.IOC和DI
1.分层解耦
- 内聚:软件中各个功能模块内部的功能联系,高内聚意味着一个模块内部的功能紧密相关、目标一致,模块内的元素相互依赖程度高,通常表现为模块的功能单一且聚焦。
- 耦合:衡量软件中各个层/模块之间的依赖、关联的程度,低耦合意味着各个模块之间的关联较小,修改一个模块不会对其他模块造成太大影响。良好的设计中,模块之间应该尽可能地减少相互依赖,降低耦合度,提高系统的灵活性和可维护性。
- 软件设计原则:高内聚低耦合,这样的设计使得系统更易于理解、扩展和维护,有助于降低修改一个部分对系统其他部分造成的影响。
如图Controlle调用了Service,Service又调用了Dao。而Controlle在调用Service时需要用到Service的对象,所以需要在Controlle里New一个Service的实现类。
private Service service = new ServiceA();
可New了Service的实现类后,如果ServiceA这个实现类类名发生变化,或者需要切换一个实现类。这时就需要更改Controlle层的代码,此时Controlle和Service的代码就耦合了。同样的Service层也需要调用Dao,所以Service和Dao也耦合了。这不符合软件设计原则,及功能之间的联系越紧密越好,还有层与层之间的依赖、关联越低越好,最好解除耦合。
2.控制反转和依赖注入
@Autowired
private Service service;
这时需要更改上面的代码。不能直接New一个实现类,而是通过IOC容器存储这个实现类,在通过@Autowired注入给service。
- 控制反转:Inversion Of Control,简称IOC。对象的创建控制权由程序自身转移到外部(容器),IOC的核心思想是将对象之间的依赖关系委托给容器来管理,从而实现松耦合,使得程序的可维护性和可测试性更强。
- 依赖注入:Dependency Injection,简称DI。容器为应用程序提供运行时所依赖的资源,是实现IOC的一种方式,这样做的好处是可以更轻松地管理对象之间的依赖关系,提高了代码的灵活性和可重用性。
- Bean对象:在IOC容器中管理的对象通常被称为"Bean"。这些对象由IOC容器负责实例化、装配和管理其生命周期。
1.控制反转,Bean的声明
声明bean时在注解后可以指定名字,如@Component("name"),如果不指定bean的名字,会默认使用类名首字母小写作为名字
注解 | 说明 | 声明位置 |
---|---|---|
@Component | 声明bean的基础注解 | 不属于以下三类时,用此注解 |
@Controller | @Controller的衍生注解 | 标注在控制器类上 |
@Service | @Controller的衍生注解 | 标注在服务类上 |
@Repository | @Controller的衍生注解 | 标注在数据访问类上(由于与mybatis整合,很少使用,一般使用@Mapper) |
2.依赖注入,@Autowired
- 使用默认的@Autowired进行依赖注入时,如果同类型的bean只有一个,及Service类型只有一个ServiceA的存在,此时程序可以完成自动装配。
- 如果存在两个或以上相同类型的bean就不能使用默认进行依赖注入了,因为程序不清楚要注入哪一个bean。此时可以通过@Primary和@Qualifier或者@Resource三个注解其中一个来解决
1.@Primary
这个注解可以增加bean的优先级,如下代码@Autowired会将ServiceA注入。
#ServiceA中代码
@Primary
@Service
public class ServiceA implements Service {
......
}
#ServiceB中代码
@Service
public class ServiceB implements Service {
......
}
2.@Qualifier
这个注解可以配合@Autowired指定要注入的bean,如下代码指定注入了serviceA这个bean。
public class Controller{
@Qualifier("serviceA")
@Autowired
private Service service;
}
3.@Resource
使用该注解不需要配合@Autowired,而是直接指定注入bean的名字。区别于@Autowired,@Autowired是根据类型注入,而@Resource是根据名称注入。
public class Controller{
@Resource(name="serviceB")
private Service service;
}