Spring 设计可替换依赖项
问题描述
我一直在学习Spring以重返Java(我在专业经验方面是C#,ASP.NET Core)。有一件事情有些不同,那就是Spring缺少基于接口的DI。在.NET中,例如,我可能会有一个按照如下方式排列的三层应用程序:
-API项目
-—Controllers\WeatherController.cs
-核心项目
-—IWeatherService.cs
-数据项目
-—OpenWeatherMapWeatherService.cs
在DI容器配置中,我将使用OpenWeatherMapWeatherService关联IWeatherService的依赖项。如果我以后想要使用Weather Channel,我可以添加WeatherChannelWeatherService.cs并更新IWeatherService的配置,将其指向WeatherChannelWeatherService。
是否有Spring中的一种常见方法,允许以这种方式替换依赖项?或者构造函数/设置器DI实际上不能提供这样的机制?
解决方案
- 与问题的三层部分相关。 您可以通过将每个层放在一个单独的包中,或将其放在一个单独的源目录中,来实施n层(3层或更多层)架构。 您可以为表示层创建一个包,并将控制器放在其中。 另一层用于业务逻辑(在该层中放置所有抽象),并将所有服务与其实现放在该层中。 数据访问层用于放置所有实体和存储库。
-
与可替换的接口/组件相关。 无论您在哪里工作,您都希望拥有接口和实现,以便更容易替换实现, 因此,在Spring Boot中,您可以在控制器(表示层)中使用服务接口(服务层)作为服务实现实例的类型, 并传入一个提供的实现(例如使用@Autowired注解来注入实现对象),如果有多个实现适用于具体服务,则可以使用@Qualifier注解。
考虑下面提供的代码
这个控制器使用EmployeeService接口作为服务实现对象的类型(注意,在这个例子中,框架自动注入EmployeeService实例而不使用Autowired注解,这是平台允许的另一种注入对象的方法)
RestController:
@RestController
@RequestMapping("/api")
public class EmployeeRestController {
private EmployeeService employeeService;
public EmployeeRestController(EmployeeService employeeService) {
this.employeeService = employeeService;
}
@GetMapping("/employees")
public List<Employee> findAll() {
return employeeService.findAll();
}
...
}
服务接口:
public interface EmployeeService {
public List<Employee> findAll();
public Employee findById(int theId);
...
}
服务实施:
@Service
public class EmployeeServiceImpl implements EmployeeService {
private EmployeeDAO employeeDAO;
@Autowired
public EmployeeServiceImpl(EmployeeDAO employeeDAO) {
this.employeeDAO = employeeDAO;
}
@Override
@Transactional
public List<Employee> findAll() {
return employeeDAO.findAll();
}
...
}