我正在考虑这个构建器类,它应该根据字段值计算哈希值。对于初学者来说,也许这本身就是错误的,但目前在我看来,它属于那里,因为我正在努力写一篇不可变的文章
。
我想 Autowiring /注入(inject)ArticleMD5HashCalculator
,但是当我将@Autowired
放在字段上时,IntelliJ提示:不建议进行字段注入(inject)。构造函数注入(inject)是不可能的,因为它是一个构建器模式类,这意味着它有一个不带参数的私有(private)构造函数和一个用于实例化的静态方法,在该方法中传入 hashCalculator 会很尴尬。
构建器被注入(inject)到刮刀中。抓取工具将为许多文章重复使用相同的构建器。当 Spring 创建具有原型(prototype)范围的构建器时,当下一篇文章不覆盖旧值时,构建器将携带旧值。
新建 hashCalculator 结果是一种硬依赖,因此注入(inject)模拟是不切实际的。处理这种情况的最佳方法是什么?
这是现在的代码:
import org.observer.media.utils.ArticleMD5HashCalculator;
import org.observer.media.utils.MD5HashCalculator;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class ArticleBuilder {
private ArticleMD5HashCalculator hashCalculator;
private String headline;
private String subheading;
private String lead;
// other article fields...
private ArticleBuilder() {
// This seems wrong.
this.hashCalculator = new ArticleMD5HashCalculator(new MD5HashCalculator());
}
public static ArticleBuilder article() {
return new ArticleBuilder();
}
public ArticleBuilder withHeadline(String headline) {
this.headline = headline;
return this;
}
//Other with-methods...
public Article build() {
// calculateHash() is called in the 9th argument.
return new Article(headline, subheading, lead, body, images, quotations, subArticles, url, calculateHash(), author, sources, category, subjects, index, medium, company, datePublished, dateFetched);
}
private String calculateHash() {
return hashCalculator.hash(headline, subheading, lead, body, quotations, datePublished, dateFetched);
}
}
最佳答案
假设:
- ArticleBuilder 和 ArticleMD5HashCalculator 之间存在一对一的关系。这意味着您不打算在项目的不同位置将 hashCalculator 的不同实例注入(inject)到 ArticleBuilder 中(本质上有多个 ArticleBuilder 实例)
您可以按如下方式更改 ArticleBuilder impl
public class ArticleBuilder {
private ArticleMD5HashCalculator hashCalculator;
public ArticleBuilder(ArticleMD5HashCalculator hashCalculator) {
this.hashCalculator = hashCalculator;
}
}
您可以创建 ArticleMD5HashCalculator
类型的 spring bean并将其注入(inject) ArticleBuilder
类型的 spring bean 中以下方式。
@Configuration
public class ArticleConfig {
@Bean
public ArticleMD5HashCalculator articleMD5HashCalculator() {
return new ArticleMD5HashCalculator(new MD5HashCalculator());
}
@Bean
public ArticleBuilder() {
return new ArticleBuilder(articleMD5HashCalculator());
}
}
您可以 Autowiring ArticleBuilder
在项目的其他地方并将其用作构建器。
我不知道为什么你创建了一个私有(private)构造函数和一个静态方法来调用它。我认为这是因为您想要一个单例 ArticleBuilder。通过上述方法就可以实现这一点。如果我的理解有误,请纠正我。
更新1:
根据您在评论中提供的信息,您正在注入(inject) ArticleBuilder
在 Scraper
对象,并且您希望有一种方法来获取 ArticleBuilder
的新实例每次。您可以使用 Spring @Lookup
对此的注释。
Scraper
的 stub 实现类。
public class Scraper {
//assuming this is the method where you want to use ArticleBuilder
public void scrape() {
getArticleBuilder();
}
//You can even pass constructor arguments to this method.
//They will be used to match a constructor on the target bean and that gets invoked
@Lookup
public ArticleBuilder getArticleBuilder() {
//Spring creates a runtime implementation of this method.
return null;
}
}
您可以调用getArticleBuilder
任何时候你想要一个新的 bean 实例。如果它被声明为原型(prototype),您将始终获得该 bean 的新实例。
但唯一需要注意的是,Lookup 注释不适用于使用 @Bean
创建的 bean。注解。您的备用配置可能如下所示。
@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class ArticleBuilder {
@Autowired
private ArticleMD5HashCalculator hashCalculator;
public ArticleBuilder(ArticleMD5HashCalculator hashCalculator) {
this.hashCalculator = hashCalculator;
}
}
@Component
public class ArticleMD5HashCalculator {
public ArticleMD5HashCalculator(MD5HashCalculator hashCalculator) {
this.hashCalculator = hashCalculator;
}
}
beans.xml:
<beans>
<bean class="MD5HashCalculator" />
<!-- Fully qualified class name is needed -->
</beans>
关于java - 使用静态实例化方法在构建器类中 Autowiring 依赖项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45188315/