您能帮我摆脱ApplicationContext
吗?
我有一家工厂,所以所有的书本都是弹跳豆。 我认为这是使所有豆子都变豆的好决定。
@Component
public class BookFactoryImpl implements BookFactory {
private final ApplicationContext applicationContext;
@Autowired
public BookFactoryImpl(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Override
public Book createBook(String name) {
return applicationContext.getBean(Book.class, name);
}
}
这是带有@Bean
方法的配置类,用于实例化Book
类的新实例:
@Configuration
@ComponentScan({"factory"})
public class AppConfig {
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Lazy
public Book book(String name) {
return Book.builder().name(name).build();
}
}
这是我的Book
实体类:
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Getter
@EqualsAndHashCode
@ToString
@Builder
public class Book {
@Id
@GeneratedValue
private int id;
@Basic(fetch = FetchType.LAZY)
private String name;
}
我还有一个主意-用BookFactoryImpl
注释@Configuration
并在其中移动@Bean
方法,但是在这种情况下,我的工厂将变成@Configuration
类生命周期破裂。
您如何看待?实现工厂的最佳方法是什么?如何减少诸如ApplicationContext
之类的外部依赖关系?
或者用@Configuration
方法将所有工厂都设为@Bean
类也许很好,您如何看待?
答案 0 :(得分:3)
不,最好不要让Spring管理应用程序中的每个类。
JPA实体通常应由您在Spring托管bean中的代码实例化。
答案 1 :(得分:0)
我通常使用以下方法:
定义将包含对工厂的依赖关系的单例bean:
public class MyService {
private final Provider<Book> bookFactory;
public MyService(Provider<Book> bookFactory) {
this.bookFactory = bookFactory;
}
public void doSomething() {
Book book = bookFactory.get();
book.setNumberOfReaders(numOfReaders); // this is a drawback, book is mutable, if we want to set runtime params (like numberOfReaders)
....
}
}
现在为book bean定义一个原型:
@Configuration
public class MyConfiguration {
@Bean
@Scope("prototype")
public Book book(...) {
return new Book(...);
}
@Bean // scope singleton by default
public MyService myService(Provider<Book> bookFactory) {
return new MyService(bookFactory);
}
}
注意,提供者的类型为“ javax.inject.Provider”,以便使用id导入(例如在maven中):
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
Spring可以从4.x(我猜为4.1)开始处理此问题,而无需任何其他配置
当然,这种方法消除了向工厂注入应用程序上下文以及通常维护工厂的需求
一个缺点是它不允许使用参数构建对象,这些参数必须在运行时指定。
还有另一种方法,与@Lookup
批注一起运行时生成子类,其描述为Here,但IMO Provider方法更好。