spring配置的可选方案
Spring容器负责创建应用程序中的bean并通过DI来协调这些对象之间的关系。作为开发人员需要告诉spring需要装配哪些bean并且如何将其装配到一起。spring提供了三种主要的装配机制
- 在xml中进行显示的装配
- 在Java中进行配置
- 隐形的bean发现机制和自动配置
提供3种配置方案并不会使spring变得复杂。每种配置技术所提供的功能会出现一些重叠,所以在特定的场景中,确定哪种技术最为合适就会变得有些困难,但是不必紧张——在很多场景下,选择那种方案很大程度上只是个人的喜好问题,你尽可能选择自己喜欢的方式。并没有唯一的答案,你所做出的选择必须要适合你和你的项目。而且,我们也不是只能选择一种配置方案,spring的配置风格可以事互相搭配的,所以可以选择使用xml装配一些bean,使用spring基于Java的配置(JavaConfig)来装配另外一些bean,而将剩下的bean让spring去自动发现。
即便如此,我们建议是尽可能地使用自动配置机制。显式配置越少越好。当你必须要显式配置bean的时候(比如,有些源代码不是由你自己来维护的,而当你需要为这些代码配置bean的时候),我推荐使用类型安全并且比xml更佳强大的JavaConfig。最后,只有当你要想使用便利的xml命名空间,并且在JavaConfig中没有同样的实现的时候,才应该使用xml
自动化装配bean
如果spring能够进行自动化装配的话,那又何苦还要显示地将这些bean装配到一起?
spring 从两个角度来实现自动装配
- 组件扫描(component scanning):spring会自动发现应用上下文中所创建的bean
- 自动装配(autowiring):spring自动满足bean之间的依赖
组件扫描和自动装配组合到一起就能发挥巨大的威力,它能够将显式配置降低到最少。
通过CD播放器的例子来说明自动化装配
maven pom.xml 依赖
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.11.RELEASE</version>
</dependency>
<!--spring test包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.11.RELEASE</version>
<scope>provided</scope>
</dependency>
</dependencies>
CompactDisc接口 【CD】
package soundsystem;
public interface CompactDisc {
void play();
}
CompactDisc实现类SgtPeppers
package soundsystem;
import org.springframework.stereotype.Component;
@Component
public class SgtPeppers implements CompactDisc {
private String title="远走高飞";
private String artist="金志文"; //artist 中文为艺术家 画家的意思
public void play() {
System.out.println("Playing "+title+" by "+artist);
}
}
**java配置类CDPlayerConfig **
package soundsystem;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan
public class CDPlayerConfig {
}
**测试类CDPlayerTest **
package soundsystem;
import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=CDPlayerConfig.class)
public class CDPlayerTest {
@Autowired
private CompactDisc cd;
@Test
public void cdShouldNotBeNull(){
assertNotNull(cd);
}
}
划重点
@Component这个简单的注解表明该类会作为组件类,并告知spring要为这个类创建bean。
在程序中没有必要显式配置SgtPeppers bean,因为这个类使用了@Component注解,所以spring会为你把事情处理妥当不过,组件扫描默认是不启用的。我们还需要显示配置一下spring,从而命令它去寻找带有@Component注解的类,并为其创建bean类CDPlayerConfig通过java代码定义了spring的装配规则,类中并没有显式地声明任何bean,只不过它使用了@ComponentScan注解,这个注解能够在spring中启用组件扫描,如果没有其他配置的话,@ComponentScan默认会扫描与配置类相同的包,如果你更倾向于通过xml启用组件扫描的话,可以使用Spring context命名空间的<context:component-scan>元素。在xml中的beans标签中添加
<context:component-scan base-package="soundsystem">
CDPlayerTest使用了Spring的SpringJUnit4ClassRunner,以便在测试开始的时候自动创建Spring的应用上下文。注解@ContextConfiguration会告诉它需要在CDPlayerConfig中加载配置。
为组件扫描的bean命名
Spring应用上下文中所有的bean都会给定一个ID,在前面的例子当中,尽管我们并没有明确的给SgtPeppers bean设置ID,但Spring会根据类名为其指定一个ID。具体来讲,这个bean所给定的ID为sgtPeppers,也就是将类名的第一个字母变为小写。
如果想为这个bean设置不同的ID,你所需要做的就是将期望的ID作为值传递给@Component注解。比如说,如果想将这个bean标识为loneyHeartsClub,那么你需要将SgtPeppers类的@Component注解配置为如下所示:
@Component("loneyHeartsClub")
public class SgtPeppers implements CompactDisc{
...
}
还有另外一种为bean命名的方式,这种方式不使用@Component注解,而是使用java依赖注入规范(Java Dependency Injection)中所提供的@Named注解来为bean设置ID:
package soundsystem;
import javax.injection.Named;
@Named("loneyHeartsClub")
public class SgtPeppers implements CompactDisc{
...
}
Spring 支持将@Named作为@Component注解的替代方案。两者之间有一些细微的差异,但是大多数场景中,他们是可以相互替代的。
不过我觉得就名字上而言,对于@Named并没有像@Component那样清楚的表明它是做什么的
网友评论