类型 | 解释 | xml配置 |
---|---|---|
byName | 根据Bean的name或者id | <bean id="bean" class="…" autowire="byName"/> |
ByType | 根据Bean类型自动装配 | <bean id="bean" class="…" autowire="byType"/> |
contructor | 根据Bean的构造器入参具有相同类型 | 同上 |
Autodetect | 首先使用contructor,失败再尝试byType | 同上 |
byType在出现多个匹配项时不会自动选择一个然是报错,为避免报错,有两种办法:1.使用<bean>元素的primary属性,设置为首选Bean,但所有bean的默认primary都是true,因此我们需要将所有非首选Bean设置为false;2.将Bean的autowire-candidate
熟悉设置为false ,取消 这个Bean的候选资格,这个Bean便不会自动注入了。
contructor自动装配和byType有一样的局限性,当发现多个Bean匹配某个构造器入参时,Spring不会尝试选择其中一个;此外,如果一个类有多个构造器都满足自动装配的条件,Spring也不会猜测哪个更合适使用。
如果需要为Spring应用上下文中的每个Bean(或者其中的大多数)配置相同的autowire属性,可以在根元素<beans>上增加一个default-autowire属性,默认该属性设置为none。该属性只应用于指定配置文件中的所有Bean,并不是Spring上下文中的所有Bean。
当我们对某个Bean使用了自动装配策略,并不代表我们不能对该Bean的某些属性进行显示装配,任然可以为任意一个属性配置<property>元素,显式装配将会覆盖自动装配。但是当使用constructor自动装配策略时,我们必须让Spring自动装配构造器所有入参,不能使用<constructor-arg>元素进行混合。
从Spring2.5开始,可以使用注解自动装配Bean的属性,使用注解允许更细粒度的自动装配,可选择性的标注某一个属性来对其应用自动装配。Spring容器默认禁用注解装配,需要在Spring配置中启用,最简单的启用方式是使用Spring的context命令空间配置中的<context:annotation-config>
,如下所示:
<beans ...>
<context:annotation-config/>
<!-- bean declarations go here -->
</beans>
Spring3支持几种不同的用于自动装配的注解:
@Autowired用于对被注解对象启动ByType的自动装配,可用于以下对象:
在使用@Autowired时有两种情况会出错:没有匹配的Bean和存在多个匹配的Bean,但是都有对应的解决方法。
为统一各种依赖注入框架的编程模型,JCP(Java Community Process)发布的Java依赖注入规范,被称为JSR-330,从Spring3开始,Spring已经开始兼容该依赖注入模型。
和@Autowired一样,@Inject可以用来自动装配属性、方法和构造器。但是@Inject没有required属性,因此依赖关系必须存在,如不存在将抛出异常。
JSR-330还提供另一种注入技巧,注入一个Provider。Provider接口可以实现Bean引用的延迟注入以及注入Bean的多个实例等功能。
例如我们有一个KnifeJuggler类需要注入一个或多个Knife实例,假设Knife Bean的作用域声明为prototype,下面的KnifeJuggler的构造器将获得多个Knife Bean:
private Set<Knife> knifes;
@Inject
public KnifeJuggler(Provider<Knife> knifeProvider){
knives = new HashSet<Knife>();
for(int i=0;i<5;i++){
knives.add(knifeProvider.get());
}
}
相对于@Autowired所对应的@Qualifier,@Inject对应的是@Named注解。事实上JSR-330中也有@Qualifier注解,不过不建议直接使用,建议通过该注解来创建自定义的限定注解,和Spring的@Qualifier创建过程类似。
Spring3中引入的@Value
属性可用来装配String类型的值和基本类型的值。借助SpEL表达式,@Value不光可以装配硬编码值还可以在运行期动态计算表达式并装配,例如下面的:
@Value("#{systemProperties.name}")
private String name;
在Spring中使用上面说到的<context:annotation-config>
,可以做到自动装配,但还是要在xml中申明Bean。Spring还有另一个元素<context:component-scan>
,元素除了完成自动装配的功能,还允许Spring自动检测Bean和定义Bean ,用法如下:
<beans ...>
<context:component-scan base-package="com.springtest">
</context:component-scan>
</beans>
开启后支持如下注解:
注解 | 解释 |
---|---|
@Component | 通用的构造型注解,标识类为Spring组件 |
@Controller | 标识该类定义为Spring MVC controller |
@Repository | 标识该类定义为数据仓库 |
@Service | 标识该类定义为服务 |
使用上述注解是Bean的ID默认为无限定类名。使用@Component("name")
指定ID。
通过为配置和子元素,我们可以随意调整扫描行为。下面的配置自动注册所有的TestInterface实现类:
<context:component-scan base-package="com.fxb.springtest">
<context:include-filter type="assignable"
expression="com.fxb.springTest.TestInterface"/>
</context:component-scan>
其中的type和expression属性一起协作来定义组件扫描策略。type有以下值可选择:
过滤器类型 | 描述 |
---|---|
annotation | 过滤器扫描使用指定注解所标注的类。通过expression属性指定要扫描的注解 |
assignable | 过滤器扫描派生于expression属性所指定类型的那些类 |
aspectj | 过滤器扫描于expression属性所指定的AspectJ表达式所匹配的那些类 |
custom | 使用自定义的org.springframework.core.type.TypeFilter实现类,该类由expression属性指定 |
regex | 过滤器扫描类的名称与expression属性所指定的正则表达式所匹配的类 |
exclude-filter使用和include-filter类似,只是效果相反。
在Spring3.0中几乎可以不使用XML而使用纯粹的Java代码来配置Spring应用。
<context:component-scan>
,该标签还会自动加载使用@Configuration
注解所标识的类