我对这段代码有点怀疑,因为它有点违反了 YAGNI。我的服务类需要一些公共(public)静态字段,但当您的服务 bean 中有这些字段时,通常这是一个糟糕的设计,因此我为该服务创建了一个接口(interface),但我不确定这是正确的选择。我应该在服务类中包含这些字段吗?
public interface IYouTubeServiceBuild {
/**
* Define a global instance of the HTTP transport.
*/
public static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
/**
* Define a global instance of the JSON factory.
*/
public static final JsonFactory JSON_FACTORY = new JacksonFactory();
/**
* Define a global variable that identifies the name of a file that
* contains the developer's API key.
*/
public static final String PROPERTIES_FILENAME = "youtube.properties";
}
@Service
@Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)
public class YouTubeServiceBuild implements IYouTubeServiceBuild {
@Getter
private Properties properties;
/**
* Define a global instance of a Youtube object, which will be used
* to make YouTube Data API requests.
*/
@Getter
private YouTube youtube;
@PostConstruct
public void init() {
properties = new Properties();
youtube = new YouTube.Builder(HTTP_TRANSPORT, JSON_FACTORY, request -> {
}).setApplicationName("youtube-search-demo").build();
//etc...
}
}
}
上述服务类然后在其他服务中使用,如下所示:
@Service
public class YouTubeApiService {
@Autowired
private YouTubeServiceBuild serviceBuild;
public List<SearchResult> searchYouTube(String searchQuery) {
List<SearchResult> searchResults =
executeSearch(searchQuery, serviceBuild.getProperties(), serviceBuild.getYoutube());
//etc...
}
最佳答案
如果问题是是否可以在 Spring 托管 bean 中设置公共(public)静态字段 - 那么是的,它是可能的,尽管我完全同意你的观点,认为这是一个糟糕的设计。
不考虑 spring,将常量放入接口(interface)中以便接口(interface)的实现能够访问它们被认为是代码味道,因为所有实现(假设有很多)现在可以表现不同,因为一些常量发生变化,或者更糟糕的是 - 如果删除常量,将不再编译(如果不是所有实现都在项目中怎么办)。
更好的方法是创建一类常量:
public class YouTubeConstants {
public static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
public static final JsonFactory JSON_FACTORY = new JacksonFactory();
...
}
在需要访问这些常量的类中,您可以使用 YouTubeConstants.HTTP_TRANSPORT
(甚至可以使用静态导入来缩短)。
现在对于所提出的设计,让我提出一个替代方案:
YouTubeApiService
类基本上只需要访问 YouTube
对象,它需要它来执行查询。不需要 YouTubeServiceBuild
中间对象,不需要连接属性),恕我直言,它只会使代码变得复杂。
你可以这样做:
@Service
public class YouTubeApiService {
@Autowired
private YouTube youtube;
public List<SearchResult> searchYouTube(String searchQuery) {
List<SearchResult> searchResults =
executeSearch(searchQuery,youtube);
//etc...
}
}
看起来好多了,不是吗?
现在为了创建一个 youtube 对象,您需要一些超出常规"new"范围的代码。您可以为此使用配置:
import static YoutubeConstants.*;
@Configuration
public class YouTubeConfig {
@Bean
public YouTube youtube() {
return new YouTube.Builder(HTTP_TRANSPORT, JSON_FACTORY, request -> {
}).setApplicationName("youtube-search-demo").build();
}
}
在此实现中,根本不需要 YouTubeBuilder
还有一点需要考虑: 看起来你正在尝试自己加载一些属性,注意,spring 可以单独加载它。
我在问题中提出的代码中没有看到这些属性的任何实际用法,所以我无法提供工作示例,但请确保您了解如何在 spring 中加载属性,您可能会注入(inject)已经- 将属性加载到配置中的 youtube
方法中。
关于java - 我可以在服务 bean 中拥有公共(public)静态字段吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58787584/