Clever Castle
840 words
4 minutes
依赖注入实践总结
2023-02-15

依赖注入是一个被广泛使用的技术,可以用来降低代码之间的耦合度。

很多应用会有如下的代码分层结构

  1. 应用层(Controller),对用户/前端/其它服务暴露接口
  2. 服务层(Service),主要是上层应用层所重复使用的一些代码,简化代码冗余
  3. 存储层(Dao), 用来存储数据的层级

在实际开发中有以下一些总结

Service/Dao层应该谨慎依赖配置项#

Service层和Dao层不应该依赖配置文件,如果其中有代码依赖一些配置参数,应该在应用层中生成改服务的实例并注册。这样做的原因是,service层会被很多应用依赖,许多service只有部分应用需要到,但是如果在service中就依赖某些配置,那么这些配置在所有应用中都需要提供。当然,如果某些服务是非常基础的,基本可以确定被所有应用使用的,可以配置在service层。 由于需要在应用层中手动注册bean,而应用层的数量比较多(很多时候会有多个应用),那么需要多次手动注册bean。这边可以在应用层下设置一个common层,相对通用的bean registration可以放在其中。比较自定义的bean registration仍放在应用中。

在实际开发中,很多时候将配置项的引入放在service层中是比较方便的,且一般不会带来很大的问题。我们在开发中遇到这样的问题主要是基于以下类似的场景。

我们有多个web app,他们的依赖都比较相似,所以将配置项的引入放在service层中没有什么问题。 但是我们同时还维护了很多serverless function,而我们希望在这些serverless function中重用service层的一些代码,由于每个serverless function的功能范围很小,所以它依赖的service是很少的,但是由于很多service依赖各种配置项,所以都需要在配置文件中添加这些配置项。

如果你确定Service层只会被现有的这些应用使用,未来重用的概率也不大,其实可以在service层中依赖配置项。如果你的项目比较大,预期维护时间比较长,推荐不要在Service/Dao层中依赖配置项。

下面以spring 的DI来举例

public class ServiceA{
	@Value("a")
	private String a
}

以上代码应该转换成

public class ServiceA{
	private String a;
	public ServiceA(String a){
		this.a=a;
	}
}

那么如何在应用层使用呢?,在应用层添加如下代码即可

@Value('a')
private String a;

@Bean
public ServiceA serviceA(){
	return new ServiceA(a);
}

Service/Dao层不应该@PostConstruct @PreDestroy 方法#

这一实践总结的原因和第一条是类似的。而且由于很多时候会在PostConstruct或者PreDestroy中做一些特定的逻辑操作,而且这些操作很难追踪。如果service层有很多PostConstruct,一个会导致启动耗时增多,另外开发者可能会遗漏检查这些PostConstruct而导致错误。 所以我们不应该在Service/Dao层中使用这些方法。如果一定要使用,可以利用ImportSelector(Spring)等方法,可以在应用层手动打开/关闭这些 @PostConstruct @PreDestroy.

依赖注入实践总结
https://blog.ivyxjc.com/posts/di-practice/
Author
ivyxjc
Published at
2023-02-15