首页 > 解决方案 > 为什么我应该在 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;
    }
}

标签: springspring-bootannotationsspring-annotations

解决方案


如果一个java类被注释了@Service,Spring会管理它,它可以享受Spring提供的好处,比如应用一些AOP魔法(比如那些@Transactional@Async等等@PreAuthorize)。其他实例也可以@Autowired用来访问它而不是 DIY(即依赖注入思想)。考虑一下,如果您的对象由许多依赖项组成,而这些依赖项又由许多依赖项组成,那么手动配置该实例以具有正确的依赖关系图可能不是一件令人愉快的事情。更不用说依赖对象应该来自正确的范围。

另一方面,如果一个 java 类不需要 Spring 提供的任何特性,也许它很简单,或者它只被某些类内部使用,你可以保持简单,简单地自己创建它,例如:

ResourceManager = new FileResourceManager(formModel);

所以这取决于你是否需要一个类的弹簧特性。如果你不需要它,你可以保持简单,不需要注释@Service就可以了。


推荐阅读