在很多场景下通过组件扫描和自动装配实现Spring的自动化配置是更为推荐的方式,但有时候自动化配置的方案行不通,也就是自定义的时候。
比如说,你想要将第三方库中的组件装配到你的应用中,在这种情况下,是没有办法在它的类上添加@Component和@Autowired注解的,因此就不能使用自动化装配的方案了。
目录
进行显式配置的时候,有两种可选方案:Java和XML。
显式配置时,JavaConfig是更好的方案,因为它更为强大、类型安全并且对重构起来更加方便。因为它本身就是Java代码,就像 应用程序中的其他Java代码一样。但是要单一职责,这个配置代码,不要与业务代码混淆,JavaConfig也不应该侵入到业务逻辑代码之中,尽可能将 配置代码,放到单独包中去,这样对于它的意图就不会产生困惑了。
创建配置类
@Configuration
public class CDPlayerConfig {
...
}
随便创建一个类,然后 添加@Configuration注解,@Configuration注解表明这个类是一个配置类。
与上一篇 配置类不同的是,CDPlayerConfig的@ComponentScan注解移除掉了。移除之后在进行测试,会抛异常为:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'soundsystem.CDPlayOneTest':
Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException:
Could not autowire field:
private soundsystem.CompactDisc soundsystem.CDPlayOneTest.cd;
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type [soundsystem.CompactDisc] found for dependency:
expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations:
{@org.springframework.beans.factory.annotation.Autowired(required=true)}
会报一些很长的错,看到最后是说 required 为 true,他默认值为 true,为了避免异常的出现,你可以将@Autowired的required属 性设置为false。但是这不是解决这个问题的方法。
这个问题就是说 Could not autowire field,注入失败,测试期望被注入CDPlayer和CompactDisc,但是这些bean根本就没有创建,因为组件扫描不会发现它们。这要是@ComponentScan注解的作用所在。
声明简单的bean
比方说,下面的代码声明了CompactDisc bean:
package soundsystem;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class CDPlayerConfig {
/**
* compactDisc
*
* @param
* @return soundsystem.CompactDisc
* @author imenger
* @date 2021/2/25 10:20 上午
* @Bean注解会告诉Spring这个方法将会返回一个对象,该对象要注册为Spring应用上下文中的bean。
*/
@Bean
public CompactDisc compactDisc() {
return new SgtPeppers();
}
}
bean的ID与带有@Bean注解的方法名是一样的。在本例中,bean的名字将会是sgtPeppers。如果你想为其设置成一个不同的 名字的话,那么可以重命名该方法,也可以通过name属性指定一个不同的名字:
@Bean(name = "vcd")
@Bean注解到底是做啥的?
借助JavaConfig实现注入
我们需要 声明CDPlayer这个bean,它依赖于CompactDisc。在JavaConfig中,要如何将它们装配在一起呢?
在JavaConfig中装配bean的最简单方式就是引用创建bean的方法。例如,下面就是一种声明CDPlayer的可行方案:
@Bean
public CDPlayer cdPlayer() {
return new CDPlayer(compactDisc());
}
同样使用了@Bean注解,所以,调用 compactDisc() 方法也就创建了一个 CompactDisc 类,最终创建 CDPlayer 类。这表明这个方法会创建一个bean实例并将其注册到Spring应用上下 文中。所创建的bean ID为cdPlayer,与方法的名字相同。
以上调用有点循环嵌套,看上去有点繁琐,其是可以直接传参调用。
@Bean
public CDPlayer cdPlayer(CompactDisc compactDisc) {
return new CDPlayer(compactDisc);
}
通过这种方式引用其他的bean通常是最佳的选择,因为可以直接将 CompactDisc 类注入进来,不用 在调用 compactDisc() 这个方法。
小结
其是这个 @Bean 注解,不仅仅可以用在声明 类的方法上,或者 单独的 setter 方法上,只要你想用,在满足你的需求上 哪里都能用。
这个配置就等同于之前在xml里的配置,下篇文章会写到 xml 的配置,xml 的配置大家应该用的 比较多点,也是很多人都认可的配置方式。
<beans>
<bean id="transferService" class="com.acme.TransferServiceImpl"/>
</beans>