我对此代码有点怀疑,因为它违反了YAGNI。我的服务类需要一些公共静态字段,但是当您在服务bean中包含这些字段时,通常这是一个糟糕的设计,因此我为该服务创建了一个接口,但是我不确定这是正确的选择。我应该在服务等级中包含这些字段吗?
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...
}
答案 0 :(得分:1)
如果问题是是否有可能在Spring受管bean中设置公共静态字段,那么是的,有可能,尽管我完全同意您的看法,这是一个糟糕的设计。
不考虑弹簧问题,将常量放在接口中以便接口的实现能够访问它们被认为是一种代码味道,因为所有的实现(假设有很多)现在都可能表现不同,因为某些常量发生了变化,或者更糟糕的是-如果删除了常量(如果不是所有的实现都在项目中,该常量就不会再编译)了。
更好的方法是创建一类常量:
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对象,您需要一些代码,这些代码要比常规的“新”代码稍大一些。您可以为此使用配置:
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中加载属性,您可能已经注入了将属性加载到配置中的youtube
方法中。