spring - 为什么我应该在 Spring Boot 中使用 @Service 构造型?
问题描述
我知道@Service 是@Component 的一种,就像@Controller 和@Repository 一样。我也明白这些类型级别(类级别)的构造型有助于组件扫描在你的 spring 项目中选择不同的类型。
我注意到我创建的一个处理业务逻辑的 FileResourceManager 类在没有 @Service 的情况下工作得很好。我想更好地理解这种刻板印象的作用,以及它为什么有用。如果有助于解释@Component,请这样做。
这是一个示例类,我很想将@Service 添加到其中,因为它根据从@Controller 类收集的信息为与运行业务逻辑的 spring 无关的包准备文件
@Service
public class FileResourceManager {
private ConfigProp configProp;
@Autowired
private FormModel formModel;
public FileResourceManager(FormModel formModel) {
this.formModel = formModel;
}
public FormModel getformModel() {
return formModel;
}
public void init() throws IOException {
System.out.println("Initializing resources...");
clearDirectories();
writeTextboxToInputDirectories();
writeMultifileToInputDirectories();
}
private void clearDirectories() throws IOException {
configProp = configProp.getInstance();
RwUtils.clearDirectory(System.getProperty("user.dir")+configProp.getProperty("input.dir")+"input/");
RwUtils.clearDirectory(System.getProperty("user.dir")+configProp.getProperty("input.dir")+"file/");
}
private void writeMultifileToInputDirectories() throws IOException {
configProp = configProp.getInstance();
String inputDir = System.getProperty("user.dir")+configProp.getProperty("input.dir")+"input/";
String fileDir = System.getProperty("user.dir")+configProp.getProperty("input.dir")+"file/";
RwUtils.writeMultipartIntoFile(fileDir,formModel.getFile1());
RwUtils.writeMultipartIntoFile(fileDir,formModel.getFile2());
RwUtils.writeMultipartIntoFile(fileDir,formModel.getFile3());
for (MultipartFile record: formModel.getFiles4()) {
RwUtils.writeMultipartIntoFile(inputDir,record);
}
}
private void writeTextboxToInputDirectories() throws IOException {
configProp = configProp.getInstance();
String inputDir = System.getProperty("user.dir")+configProp.getProperty("input.dir")+"input/";
String fileDir = System.getProperty("user.dir")+configProp.getProperty("input.dir")+"file/";
if(formModel.getFile1File().isEmpty()) RwUtils.writeStringToFile(fileDir+"file1.txt",formModel.getFile1Text());
if(formModel.getFile2File().isEmpty()) RwUtils.writeStringToFile(fileDir+"file2.txt",formModel.getFile2Text());
if(formModel.getFile3File().isEmpty()) RwUtils.writeStringToFile(fileDir+"file3.txt",formModel.getFile3Text());
int i = 1;
String recordFileStr;
for (String record:formModel.getOldJsonText().split(";;;")) {
recordFileStr = inputDir+"textboxRecord"+i+".json";
RwUtils.writeStringToFile(recordFileStr,record);
i++;
}
}
// this class calls logic from a package that has no relation to spring-boot framework
public void runBusinessLogic() throws IOException, InvalidEntryException {
// logic
}
public void download(ZipOutputStream zippedOut) throws IOException {
ConfigProp configProp = ConfigProp.getInstance();
String downloadFormat = getformModel().getDownloadFormat();
FileSystemResource resource;
ZipEntry zipEntry;
File dir;
for (String dirStr:downloadFormat.split("-")) {
dir = new File(System.getProperty("user.dir")+configProp.getProperty("output.dir")+dirStr);
for (File file:dir.listFiles()) {
resource = new FileSystemResource(System.getProperty("user.dir")+configProp.getProperty("output.dir")+dirStr+"/"+file.getName());
zipEntry = new ZipEntry(file.getName());
// Configure the zip entry, the properties of the file
zipEntry.setSize(resource.contentLength());
zipEntry.setTime(System.currentTimeMillis());
// etc.
zippedOut.putNextEntry(zipEntry);
// And the content of the resource:
StreamUtils.copy(resource.getInputStream(), zippedOut);
zippedOut.closeEntry();
}
}
zippedOut.finish();
}
public static void main(String[] args) throws IOException {
// used to test runBusinessLogic() method
}
}
这是一个示例服务类,其中 @Service 似乎很重要
@Service
public class MyUserDetailsService implements UserDetailsService {
@Autowired
private MyUserRepository repo;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
MyUser user = repo.findByUsername(username);
if(user==null)
throw new UsernameNotFoundException("Username not found");
return new UserPrincipal(user);
}
public MyUser getUser(String username) throws UsernameNotFoundException {
MyUser user = repo.findByUsername(username);
if(user==null)
throw new UsernameNotFoundException("Username not found");
return user;
}
public MyUser createUser(MyUser user) {
String email = user.getEmail();
String username = user.getUsername();
if(repo.existsUserByEmail(email)) {
user = repo.findByEmail(email);
} else if(repo.existsUserByUsername(username)) {
user = repo.findByUsername(username);
} else {
this.repo.save(user);
user = repo.findByEmail(email);
}
return user;
}
}
解决方案
如果一个java类被注释了@Service
,Spring会管理它,它可以享受Spring提供的好处,比如应用一些AOP魔法(比如那些@Transactional
,@Async
等等@PreAuthorize
)。其他实例也可以@Autowired
用来访问它而不是 DIY(即依赖注入思想)。考虑一下,如果您的对象由许多依赖项组成,而这些依赖项又由许多依赖项组成,那么手动配置该实例以具有正确的依赖关系图可能不是一件令人愉快的事情。更不用说依赖对象应该来自正确的范围。
另一方面,如果一个 java 类不需要 Spring 提供的任何特性,也许它很简单,或者它只被某些类内部使用,你可以保持简单,简单地自己创建它,例如:
ResourceManager = new FileResourceManager(formModel);
所以这取决于你是否需要一个类的弹簧特性。如果你不需要它,你可以保持简单,不需要注释@Service
就可以了。
推荐阅读
- cadence-workflow - 时间工作流程与节奏工作流程
- confluence-rest-api - 使用 Confluence API 使用 IFrame 宏创建页面
- excel - Excel 按钮打开 VBA 屏幕而不是运行代码
- c# - 如何在同一行中编写两个方法
- identityserver4 - 使用身份服务器 4 中的 CustomTokenRequestValidationContext 在令牌响应中返回用户角色
- javascript - 任何 Node.js Minifier 都支持 Javascript Null-Coalescing 运算符 (??)?
- python - 我的函数的返回是一个熊猫数据框对象,但我收到一个元组。发生了什么,我怎样才能将对象作为 DataFrame 接收?
- android - 使用 viewpager 制作图像视图
- python - Python - 测试 azure-devops / msrest ClientRequestError
- flutter - 颤振:无法获得包含行的卡片的正确大小