1.Spring配置的可选方案
Spring容器负责创建应用程序中的bean,并通过DI(依赖注入)来协调这些对象之间的关系。在描述bean如何进行装配时,Spring提供了三种主要的装配机制:
①在XML中进行显示配置
②在Java中进行显示配置
③隐式的bean发现机制和自动装配
2.自动化装配bean
Spring从两个角度来实现自动化装配:
①组件扫描(component scanning) : Spring会自动发现应用上下文中所创建的bean
②自动装配(autowiring) : Spring自动满足bean之间的依赖。
2.1创建可被发现的bean
创建可被发现的bean分为两个步骤:
①在java类上打上@Component注解。
②使用@ComponentScan注解启动组件扫描
@Component注解表明该类会作为组件类,并告知Spring要为这个类创建bean。@ComponentScan注解是用来启用Spring自动扫描组件。启动自动扫描后,Spring将自动寻找带有Spring注解的类,并为该类创建bean。
例:
package soundsystem;
@Component
public class SgtPepers{
}
这是一个普通的Java类,通过@Component注解可以将该类托管给Spring容器。但是在打开Spring自动扫描之前Spring并不会自动为这个类创建bean。所以要通过一个配置类来进行配置启用Spring自动扫描。
package soundsystem;
@Configuration
@ComponentScan
public class SgtPepersConfig{
}
@Configuration这个注解简单理解就是表明这个类是Spring的配置类。熟悉Spring xml配置的话,就是相当于beans。
启用自动扫描使用XML进行配置是:<context:component-scan>
2.2为组件扫描的bean命名
Spring应用上下文中每个bean都会指定一个ID,Spring默认给每个bean的ID是类名首字母小写。如上面的类SgtPepers在Spring容器中bena的默认ID是sgtPepers。如果想给这个类的bean设置成自定义的ID可以使用如下方式进行注解:
package soundsystem;
@Component("pepers")
public class SgtPepers{
}
这样类SgtPepers在Spring容器中bean的ID就变成了pepers。Spring支持将@Named作为@Component的替代方案。两者有细微差异,单大多说情况可以互相替换。
2.3设置组件扫描的基础包
在上面的启动Spring扫描的注解中没有为该注解设置任何属性,这样会按照Spring的默认规则会以注解类所在的包为基础包来扫描组件。如果想扫描不同的包可以在@ComponentScan注解中设置value属性。
package soundsystem;
@Configuration
@ComponentScan("packageName")
public class SgtPepersConfig{
}
@ComponentScan("pacePackageName")注解相当于@ComponentScan(basepackages="packageName")。如果扫描多个包则@ComponentScan(basePackages={"pacePackageName1","pacePackageName2",...})。
也可以这样设置@ComponentScan(basePackageClasses={类1.class,类2.class}),这样,类1和类2所在的包会做为扫描的基础包。
2.4通过为bean添加注解实现自动装配
Spring特有的注解@Autowired,@Autowired注解可以用在类的任何方法上,也可以直接用在属性上。@Autowired注解有required属性,默认是true,可以设置为false。@Autowired注解可以使用@Inject替代。
3.通过Java代码装配bean
当我们需要使用第三方库中的类时,无法在它的类上使用@Component等注解,因此无法使用自动化装配的方案。在这种情况下有两种可选方案:
①使用Java配置
②XML配置。
在进行显式配置时,JavaConfig是更好的方案。因为它更为强大、类型安全并且对重构友好。
3.1创建配置类
创建JavaConfig类的关键是在该类上添加@Configuration注解,@Configuration注解表明这个类是配置类,该类应该包含在Spring应用上下文中如何创建bean的细节。
例:
package config;
@Comfiguration
public class BeanConfig{
}
3.2声明简单的bean
要在JavaConfig中声明bean,需要编写一个方法,这个方法返回一个需要创建类型的实例,在这个方法上添加@Bean注解,将返回的对象注册为Spring应用上下文中的bean。方法体包含了产生bean实例的逻辑。
如:
@Bean
public SgtPepers sgtPepers(){
SgtPepers s = new SgtPepers();
//对实例的一些设置,比如属性设置
return s;
}
这样,通过@Bean注解,就会告诉Spring把返回的对象s注册为Spring应用上下文中的bean。默认情况下,bean的ID与带有@Bean注解的方法名一致。比如本例中bean的ID是sgtPepers。如果要使用自定义的ID话,可以在@Bean中设置name属性,如@Bean(name="pepers")。
3.3借助JavaConfig实现注入
假设有类:
public class CdPlayer{
private SgtPepers sgtPepers ;
public void setSgtPepers (SgtPepers sgtPepers ){
this.sgtPepers = sgtPepers ;
}
public SgtPepers getSgtPepers(){
return this.sgtPepers
}
public CdPlayer(){}
public CdPlayer(SgtPepers sgtPepers){
this.sgtPepers = sgtPepers;
}
}
在使用JavaConfig创建该类的bean时假设这个bean依赖一个SgtPepers 的bean,我们可以做如下配置。
package config;
@Comfiguration
public class BeanConfig{
@Bean
public SgtPepers sgtPepers(){
SgtPepers s = new SgtPepers();
//对实例的一些设置,比如属性设置
return s;
}
@Bean
public CdPlayer cdPlayer(){
//通过方法的引用依赖
return new CdPlayer(sgtPepers())
}
}
上面通过调用方法sgtPepers()注入一个bean,这种方式有局限性就是配置SgtPepers bean的方法必须在同一个配置类中。所以更为推荐的是以下配置:
package config;
@Comfiguration
public class BeanConfig{
@Bean
public CdPlayer cdPlayer(SgtPepers sgtPepers){
//通过方法的引用依赖
return new CdPlayer(sgtPepers)
}
@Bean
public CdPlayer cdPlayer(SgtPepers sgtPepers){
CdPlayer cdPlayer = new CdPlayer();
cdPlayer. setSgtPepers (sgtPepers );
}
}
由于Spring中的bean是单例的,所以上面两个不同的CdPlayer的SgtPepers属性是相同的。
@Bean注解的方法可以采用任何必要的java功能来产生bean实例。
4.通过XML装配bean
由于Spring的xml配置是我一直在使用的配置,在这不再赘述