两大技巧,减少XML配置
自动装配autowire
自动检测autodiscovery
一、自动装配Bean属性
1.四种类型的自动装配
byName:匹配ID
byType:匹配类型
constructor:把相同类型的Bean装配到该Bean构造器中
autodetect:首先用constructor,失败则用byType
(1)byName范例:
假如已有
<bean id="instrument" class="com.saxophone" />
那么
<bean id="keny" class="com.instrumentalist">
<p name="song" value="Bell" />
<p name="instrument" ref="saxophone" />
</bean>
可以改为
<bean id="keny" class="com.instrumentalist" autowire="byName">
<p name="song" value="Bell" />
</bean>
通过配置autowire,让keny bean自动查找ID为instrument的bean,装配进来
(2)byType
autowire="byType"
发现多个bean满足时,会抛出异常。
解决方法:
a.指定首选Bean, primary=true,问题是默认都为true,所以需要挨个关闭非首选;
b.取消某些Bean的候选资格,直接不参与竞争 autowire-candidate="false"。
<bean id="idname" class="com.test" primary="false" />
(3)constructor
autowire="constructor"
(4)自动最佳匹配
autowire="autodetect"
2.默认自动装配
对作用域内Bean统一设置
<beans ....... default-autowire="byName">
....
</beans>
二、使用注解装配
启用注解装配:<context:annotation-config />
有三种注解装配:
Spring自动@Autowired
JSR-330 @Inject
JSR-250 @Resource
1.@Autowired
(1)
如希望自动装配某个属性,如instrument,则对其setter方法setInstrument()方法做标注,Spring会尝试byType装配。
同时也可标注任意Bean所需使用的方法、构造函数(会自动选择参数最多的),或直接标注属性(删除setter方法)。
@Autowired
public void setInstrument(Instrument instrument)
{
this.instrument=instrument
}
(2)可选的自动装配 @Autowired(required=false)
这样如找不到合适装配,则装配Null。
(3)限定@Qualifier
限定方法、属性
@Autowired
@Qulifier("guitar")
private Instrument instrument;
限定guitar为有弦乐器(Stringed)
a.
<bean id="guitar" class="com.guitar">
<qulifier value="stringed" />
</bean>
b.
@Qualifier("Stringed")
public class Guitar implements Instrument { }
(4)创建自定义的Qualifier
@Target(ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface TestInstrument { }
2.使用@Inject
(1)基本
用法基本同@Autowired,但是没有required属性,所以必须能找到装配
Provider
(2)限定
@Named类似于@Qualifier
例如
@Inject
@Named(“guitar”)
private Instrument instrument
(3)JSR-330的 Qualifier
但是不建议用该Qualifier,而是自我创建
@Target(。。。)
@Retention(。。。)
@Qualifier
public @interface StringedInstrument { 。。。 }
3.注解中使用表达式
符号: @Value
例如
@Value(“#{sytemProperties.myFavoriteSong}”)
private String song;
三、自动检测Bean
使用<context:component-scan>替换<context:annotation-config>
可以不使用<bean>,而大多数的Bean都能够实现定义和装配。
<context:component-scan base-package="com.test">
</context:component-scan>
base-package 指定所需扫描的包,找出能够自动注册为Bean的类
1.为自动检测标注Bean
@Component 构造型注解,标识该类为Spring组件
@Controller 标识该类定义为Spring MVC controller
@Repository 标识该类定义为数据仓库
@Service 标识该类定义为服务
例:
@Component
public cliass Guitar implements Instrument {
public void play() { .. }
}
Sping会自动将其注册为Bean,ID为类名 guitar
如果改为@Component(“test”),则ID为test
2.过滤组件扫描
(1)通过为<context:component-scan>配置
<context:include-filter>自动注册所定义的类为bean
<context:exclude-filter>
(2)5种过滤器
annotation:扫描使用指定注解(expression)所标注的类
assignable:扫描派生于expression所指定类型的类
aspectj:扫描与expression所指定AspectJ表达式匹配的类
custom:使用自定义的TypeFilter实现类,该类由expression指定
regex:扫描类的名称与expression所指定的正则表达式匹配的类
(1)(2)举例
<context:component-scan base-package="com.springidol">
<context:include-filter type="assignable" expression="com.Instrument" />
<context:exclude-filter type="annotation" expression="com.SkipIt" />
</context:component-scan>
上例假设自定义了@SkipIt注解,并在某些类上标注。
注册所有继承自Instrument的类为Bean;不注册所有标注了@SkipIt的类。
四、使用Spring基于Java的配置
1.使用Java配置Spring
首先仍然需要一些XML,启用Java配置。
2.定义配置类
@Configuration相当于<beans>
@Configuration
public class Springtest {}
3.声明Bean
@Bean告知Spring该方法将返回一个对象,并被注册为Bean,ID为方法名
@Bean
public Performer duke() {
return new Juggler();
}
4.基于Java的配置实现注入
只是在方法前加@Bean,确定为bean,目的何在?大幅增加程序代码??