在Spring进行显示配置时,有两种可选方案:Java和XML。
但JavaConfig是更好的方案,因为它更为强大、类型安全并且对重构友好。
尽管在很多场景下可以通过组件扫描和自动装配实现Spring的自动化配置,但是有时候这种方案是行不通的。例如要将第三方库中的组件装配到应用中,是没有办法在它的类上添加@Component和@Autowired注解的。这种情况下必须采用显示装配的方式。
在Spring进行显示配置时,有两种可选方案:Java和XML。
但JavaConfig是更好的方案,因为它更为强大、类型安全并且对重构友好。
JavaConfig是配置代码,意味着它不应该包含任何业务逻辑,JavaConfig也不应该侵入到业务逻辑代码中去。通常会将JavaConfig放到单独的包中。
创建配置类
创建JavaConfig类的关键在于为其添加@Configuration注解,该注解表明这个类是一个配置类,该类应该包含Spring应用上下文中如何创建bean的细节。1
2
3
4
5
6
7
8
9package com.dingsheng.spring;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
public class CDPlayerConfig {
}
此处主要关注显示装配,因此删除了@ComponentScan注解
声明简单的bean
要在JavaConfig中声明bean,需要编写一个创建所需类型的实例方法,然后给这个方法添加@Bean注解,@Bean注解会高祖Spring这个方法将会返回一个对象,该对象要注册为Spring应用上下文中的bean,方法体中包含了最终产生bean实例的逻辑。1
2
3
4@Bean
public CompactDisc sgtPeppers() {
return new SgtPeppers();
}
可以使用@Bean(name=”sgtPeppers-name”)来进行自定义bean的ID。
借助JavaConfig实现注入
在JavaConfig中装配bean的最简单方式就是引用创建bean的方法。1
2
3
4@Bean
public CDPlayer cdPlayer {
return new CDPlayer(sgtPeppers());
}
这个方法也使用了@Bean注解,表明这个方法会创建一个bean实例并将其注册到Spring应用上下文中,所创建的bean ID与方法同名。
这里的sgtPeppers()方法上添加了@bean注解,Spring将会拦截所有对它的调用,并确保直接返回该方法所创建的bean,而不是每次都对其进行实际的调用。
默认情况下,Spring中的bean都是单例的,并没有必要为第二个CDPlayer bean创建完全相同的SgtPeppers实例。所以,Spring会拦截对sgtPeppers()的调用并确保返回的是Spring所创建的bean,也就是Spring本身在调用sgtPeppers()时所创建的CompactDisc bean。因此,两个CDPlayer bean会得到相同的SgtP实例。
还有另一种方式:1
2
3
4@Bean
public CDPlayer cdPlayer(CompactDisc compactDisc) {
return new CDPlayer(compactDisc);
}
在这里,cdPlayer()方法请求一个CompactDisc作为参数。当Spring调用cdPlayer()创建CDPlayer bean的时候,它会自动装配一个CompactDisc到配置方法中。然后,方法体就可以按照合适的方式来使用它。借助这种方法,cdPlayer()方法也能将CompactDisc注入到CDPlayer的构造器中,而且不用明确引用CompactDisc的@Bean方法
这种方式不会要求将CompactDisc声明到同一个配置类中,甚至没有要求CompactDisc必须要在Javaconfig中声明,实际上它可以通过组件扫描功能自动发现或者通过XML来进行配置。可以将配置分散到多个配置类、XML文件以及自动扫描和装配bean之中,只要功能健全即可。不管CompactDisc是采用什么方式创建出来的,Spring都会将其传入到配置方法中,并用来创建CDPlayer bean。