Spring 提供了几种技巧可以帮助我们减少XML的配置数量:
1.自动装配:有助于减少甚至消除配置<property>元素和<constructor-arg>元素,让Spring自动识别如何装配Bean的依赖关系。
2.自动检测:比自动装配更进一步,让Spring能够自动识别哪些类需要配置成Spring Bean,从而减少对<bean>元素的使用。当自动装配和自动检测一起使用时,他们可以显著减少Spring的XML配置数量,通常只需配置少量的几行XML代码,而无需知道在Spring的应用上下文中究竟有多少bean.
自动装配:有4种类型:
1.byName----把与Bean的属性具有相同名字(或者ID)的其他Bean自动装配到Bean对应的属性中,如果没有跟属性的名字相匹配的Bean,则该属性不进行装配。
2.byType----把与Bean的属性具有相同的类型的其他Bean自动装配到Bean的对应属性中,如果没有跟属性的类型相匹配的Bean,则该属性不被装配。
3.constructor---把与Bean的构造器入参具有相同类型的其他Bean自动装配到Bean构造器的对应入参中。
4.autodetect----首先尝试使用constructor进行自动装配,如果失败,在尝试使用byType进行自动装配。
byName自动装配:在Spring中所有的东西都会赋予一个名字,因此Bean的属性也会有名字,就像装配进属性的Bean一样,假如属性的名字恰好与要被装配到该属性的Bean的名字匹配,这个幸运的巧合暗示Spring这个Bean应该自动装配到该属性中去。
例如:
<bean id="kenny" class="com.springinaction.A" >
<property name="song" value="Jingle Bells"></property>
<property name="instrument" ref="saxophon”></property>
</bean>
在这里我们使用<property>元素显示配置了kenny的instrument属性,等一下假设使用<bean>元素在定义Saxophon时,把这个bean的ID属性设置为instrument:
<bean id="instrument" class="com.springinaction.Saxophon"/>
在本例中,Saxophon Bean的id属性与kenny Bean的instrument属性的名字是一样的,通过配置autowire属性,Spring就可以利用此信息自动装配kenny的instrument属性了,如下所示:
<bean id="kenny " class="com.springinaction.A" autowire="byName">
<property name="instrument" ref="saxophon”/>
</bean>
byName自动装配遵循一项约定:为属性自动装配ID与该属性的名字相同的Bean,通过设置autowire属性为byName,Spring将特殊对待kenny 的所有属性,为这些属性寻找与其名字相同的Spring Bean.会去找id和name
byType自动装配:byType自动装配的工作方式与byName方式类似,只不过是不再匹配属性的名字而是检查属性的类型.会去找class.
byType存在一个局限性:如果在Spring寻找到多个Bean,他们的类型与需要自动装配的属性的类型都相匹配,这种情况下,Spring不会猜测到底哪个Bean更适合自动装配,而是选择抛出异常,所以应用只允许存在一个Bean与需要自动装配的属性类型先匹配。
为了避免这种byType自动装配而带来的歧义:可以自动装配一个首选Bean(primary="true"),或者取消某个Bean的自动装配的候选资格(autowire-candidate="false")。,然而primary的默认是为true的,所以我们需要把其他不需要的设置为primary=“false”.
constructor自动装配:如果要通过构造器注入来配置Bean,那我们可以移除<constrructor-arg>元素,由Spring在应用上下文中自动选择Bean注入到构造器入参中。例如下面的例子:
<bean id="duke" class="com.jt.Test" autowire="constructor"/>
在duke Bean的新声明中,<constructor-arg>元素消失不见了,而autowire属性设置为constructor,上述声明告诉Spring去审视Test的构造器,并尝试在Spring配置中去寻找匹配Test某一构造器所有入参的Bean。
使用注解自动装配:使用注解装配与在XML中使用autowire属性自动装配并没有太大的区别,但是使用注解方式允许更细粒的自动装配,我们可以选择性地标注某一个属性来对其应用的自动装配。Spring默认是禁止注解装配的,所以在基于注解方式前,我们需要在Spring配置中启动它,最简单的方式是使用Spring的context命名空间配置中的<context:annotation-config>元素,该元素告诉Spring我们打算使用基于注解的方式自动装配,一旦配置完成,我们就可以对代码添加注解,标识Spring应该为属性,方法和构造器进行自动装配。
Spring3支持几种不同的用于自动装配的注解:
1.Spring自带的@Autowired注解
2.JSR-330的@Inject注解
3.JSR-250的@Resource注解
使用@Autowired注解:
例如下面的例子:
1.对setter方法进行标注
@Autowired
public void setInstructor(Instructor instructor){
this.instructor=instructor;
}
2.注解构造器:
@Autowired
public InstructorList(Instructor instructor){
this.instructor=instructor;
}
当对构造器进行标注时,@Autowired注解表示当创建Bean时,即使在Spring XML文件中没有使用<constructor-arg>元素配置Bean,该构造器也需要进行自动装配。
另外,我们还可以使用@Autowired注解直接标注属性,并删除setter方法,
@Autowired
private Instructor instructor;
正如我们所看到的,@Autowired甚至不会受限于private关键字,即使instructor属性是私有的实例变量,它仍然可以被自动装配。
@Autowired受限制的两种场景:如果没有Bean可以装配到@Autowired所标注的属性或者参数中,自动装配就会失败(抛出NoSuchBeanDifinitionException)
所以我们采用可选的自动装配:
@Autowired(required=false)
private Instructor instructor;
假如有多个Bean完全满足Spring完全满足装配条件,那么我们使用@Qualifier来明确指定装配哪个Bean
<context:component-scan base-package=com.xxx.xxx/ >包扫描注解:
常用的注解有:
@Controller:声明Action逐渐
@Service:声明Service组件 @Service("myMovieLister")
@Repository:声明Dao组件
@Component:泛指组件,当不好归类时
@RequestMapping("/menu") 请求映射
@Resource:用于注入,(J2ee提供的)默认按名称装配,@Resource(name="beanName")
@Autowired 用于注入,(srping提供的) 默认按类型装配
@Transactional( rollbackFor={Exception.class}) 事务管理
@ResponseBody
@Scope("prototype") 设定bean的作用域
过滤组件扫描:
事实上,在如何扫描来获取候选Bean方面上,<context:component-scan >非常灵活,通过为它配置<context:include-filter>子元素,我们可以任意调整扫描行为。
<context:exclude-filter>