在阅读Spring框架的文档时,我偶然发现了在工厂方法中传递Bean依赖关系的两种不同样式。第一个是这样的(直接使用依赖的工厂方法):
@Configuration
public class MessagingConfiguration {
@Bean
public ConnectionFactory connectionFactory() {
CachingConnectionFactory connectionFactory = new CachingConnectionFactory("localhost");
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
return connectionFactory;
}
@Bean
public RabbitTemplate rabbitTemplate() {
return new RabbitTemplate(connectionFactory());
}
}
第二个看起来像这样(将依赖项作为工厂方法中的参数注入):
@Configuration
public class MessagingConfiguration {
@Bean
public ConnectionFactory connectionFactory() {
CachingConnectionFactory connectionFactory = new CachingConnectionFactory("localhost");
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
return connectionFactory;
}
@Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
return new RabbitTemplate(connectionFactory);
}
}
我想知道两种解决方案的PRO和CON是什么,哪种更可取?
答案 0 :(得分:1)
我不相信你会对"首选"达成共识对此。
第二种风格的PRO是它按原样工作,无论依赖bean的定义在哪里。
例如,如果有问题的两个bean是在两个独立的@Configuration类中定义的,那么第一个类就会变成这样:
@Configuration
public class MessagingConfiguration1 {
@Bean
public ConnectionFactory connectionFactory() {
CachingConnectionFactory connectionFactory = new CachingConnectionFactory("localhost");
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
return connectionFactory;
}
}
@Configuration
public class MessagingConfiguration2 {
@Autowired
ConnectionFactory connectionFactory;
@Bean
public RabbitTemplate rabbitTemplate() {
return new RabbitTemplate(this.connectionFactory);
}
}
虽然第二种风格保持不变:
@Configuration
public class MessagingConfiguration1 {
@Bean
public ConnectionFactory connectionFactory() {
CachingConnectionFactory connectionFactory = new CachingConnectionFactory("localhost");
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
return connectionFactory;
}
}
@Configuration
public class MessagingConfiguration1 {
@Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
return new RabbitTemplate(connectionFactory);
}
}
第二个PRO是它可以更容易地看到bean有多少依赖项,这意味着它可能做得太多,这意味着它可能是重构的时候。
直到几周前我才意识到第二种风格,但这是我以后一直在使用的。
祝你好运!答案 1 :(得分:1)
在正常使用情况下,两种方法之间不应存在如此大的差异。但是,如果您希望将配置拆分为多个类,则不能简单地使用第一个解决方案。假设您想将两个@Bean方法放入单独的类中,并通过@Import将第一个方法导入第二个类,编译器无法知道RabbitTemplate中第一个类的connectionFactory()方法(connectionFactory( ))第二类的构造函数。所以你会遇到编译器错误。要解决此问题,您可以使用spring文档中建议的第二种方法:Injecting dependencies on imported @Bean definitions
注入对导入的@Bean定义的依赖
上面的例子很有效,但很简单。在最实际的 在这些场景中,bean将彼此依赖 配置类。使用XML时,这本身不是问题, 因为没有涉及编译器,人们可以简单地声明 ref =“someBean”并相信Spring会在容器中解决它 初始化。当然,在使用@Configuration类时,Java 编译器在配置模型上放置约束 对其他bean的引用必须是有效的Java语法。
幸运的是,解决这个问题很简单。正如我们已经讨论的, @Bean方法可以有任意数量的参数来描述 bean依赖。让我们考虑一个更真实的场景 几个@Configuration类,每个类都取决于声明的bean 其他人:
@Configuration
public class ServiceConfig {
@Bean
public TransferService transferService(AccountRepository accountRepository) {
return new TransferServiceImpl(accountRepository);
}
}
@Configuration
public class RepositoryConfig {
@Bean
public AccountRepository accountRepository(DataSource dataSource) {
return new JdbcAccountRepository(dataSource);
}
}
@Configuration
@Import({ServiceConfig.class, RepositoryConfig.class})
public class SystemTestConfig {
@Bean
public DataSource dataSource() {
// return new DataSource
}
}
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class);
// everything wires up across configuration classes...
TransferService transferService = ctx.getBean(TransferService.class);
transferService.transfer(100.00, "A123", "C456");
}
答案 2 :(得分:0)
第二个(如果您考虑在编写代码时进行测试)。始终尝试通过依赖注入来避免硬连接和创建实例,以便更容易测试代码(例如,模拟https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html)并保持可配置。