8.2 Spring的”零配置”支持
以前的Java框架大多采用XML作为配置文件,时至今日,也许是受Rails框架的启发,几乎所有的主流Java框架都打算支持"零配置"特性。现在要介绍的Spring,都开始支持使用注解来代替XML配置文件。
8.2.1 搜索Bean类
既然不再使用Spring配置文件来配置任何Bean实例,那么只能希望Spring会自动搜索某些路径下的Java类,并将这些Java类注册成Bean实例。
Rails框架的做法
Rails框架的处理比较简单,它采用一种所谓的”约定优于配置”的方式,它要求将不同组件放在不同路径下,而Rails框架中是加载固定路径下的所有组件。
Spring框架的做法
Spring没有采用”约定优于配置”的策略,** Spring依然要求程序员显式指定搜索哪些路径下的Java类, **Spring将会把合适的Java类全部注册成Spring Bean。
标注Bean类的注解
那现在的问题是:Spring怎么知道应该把哪些Java类当成Bean类处理呢?这就需要使用注解了, Spring通过使用一些特殊的注解来标注Bean类。Spring提供了如下几个注解来标注Spring Bean。
| 注解 | 描述 |
|---|---|
@Component |
标注一个普通的Spring Bean类。 |
@Controller |
标注一个控制器组件类。 |
@Service |
标注一个业务逻辑组件类。 |
@Repository |
标注一个DAO组件类。 |
如果需要定义一个普通的Spring Bean,则直接使用@Component标注即可。但如果用@Reepository、@Service或@Controller来标注这些Bean类,这些Bean类将被作为特殊的Java EE组件对待,也许能更好地被工具处理,或与切面进行关联。例如,这些典型化的注解可以成为理想的切入点目标。 |
|
@Controller、@Service和@Repository能携带更多语义,因此,如果需要在Java EE应用中使用这些标注时,应尽量考虑使用@Controller、@Service和@Repository来代替通用的 @Component标注。 |
|
| ## 使用context Schema指定搜索路径 ## | |
指定了某些类可作为Spring Bean类使用后,最后还需要让Spring搜索指定路径,此时需要在Spring配置文件中导入 context Schema,并指定一个简单的搜索路径。 |
下面示例定义了一系列Java类,并使用@Component来标注它们。
1 | package org.crazyit.app.service.impl; |
1 | package org.crazyit.app.service.impl; |
这些Java类与前面介绍的Bean类没有太大区别,只是每个Java类都使用了@Component标注,这表明这些Java类都将作为Spring的Bean类。
接下来需要在Spring配置文件中指定搜索路径, Spring将会自动搜索该路径下的所有Java类,并根据这些Java类来创建Bean实例。本应用的配置文件如下。
1 |
|
上面的配置文件中最后一行代码指定Spring将会把org.crazyit.app.service包及其子包下的所有Java类都当成Spring Bean来处理,并为每个Java类创建对应的Bean实例。经过上面的步骤, Spring容器中自动就会增加三个Bean实例(前面定义的三个类都是位于org.crazyit.app.service.impl包下的)。
主程序如下:
1 | package lee; |
上面程序中输出了Spring容器中所有Bean实例的名称,运行上面的程序,将看到如下输出结果:
1 | chinese |
使用注解方式时将类名首字母变小写得到Bean的名称
从上面的运行结果可以看出, Spring容器中三个Bean实例的名称分别为chinese、 steelAxe和stoneAxe,那么这些名称是从哪里来的呢?
- 在基于
XML配置方式下,每个Bean实例的名称都由其id属性指定的; - 在基于注解的方式下,
Spring通过将该Bean类的类名的首字母变成小写,其他字母不变的规则得到Bean的名称。
使用注解设置Bean的名称
当然Spring也允许在使用@Component标注时指定Bean实例的名称,例如如下代码片段:
1 | ("axe") |
上面程序中的粗体字代码指定该Bean实例的名称为axe.
在默认情况下, Spring会自动搜索所有以@Component、@Controller、@Service和@Repository标注的Java类,并将它们当成Spring Bean来处理。
@Lookup注解执行方法注入
Spring还提供了@Lookup注解来执行lookup方法注入,其实 @Lookup注解的作用完全等同于<lookup-method>元素。
lookup-method元素复习
使用<lookup-method>元素。需要指定如下两个属性
lookup-method元素属性 |
描述 |
|---|---|
name |
指定要执行lookup方法注入的方法名。 |
bean |
指定lookup方法要注入的Bean的id。 |
| ### @Lookup注解通过value属性指定要注入的Bean的id ### | |
而@Lookup注解则直接修饰需要执行lookup方法注入的方法,因此不需要指定name属性,该@Lookup注解要指定一个value属性, value属性就等同于<lookup-method>元素的bean属性,也就是用来指定lookup方法要注入Bean的id。 |
扫描bean的时候对bean进行过滤
除此之外,还可通过为<component-scan>元素添加<include-filter>或<exclude-filter>子元素来指定Spring Bean类,其中:
<include-filter>用于强制Spring处理某些Bean类,即使这些类没有使用Spring注解修饰;<exclude-filter>则用于强制将某些Spring注解修饰的类排除在外。
include-filte元素
<include-filter>元素用于指定满足该规则的Java类会被当成Bean类处理,<exclude-filter>指定满足该规则的Java类不会被当成Bean类处理。使用这两个元素时都要求指定如下两个属性:
| 属性 | 描述 |
|---|---|
type |
指定过滤器类型。 |
expression |
指定过滤器所需要的表达式。 |
Spring内建支持如下4种过滤器。
| 过滤器 | 描述 | ||
|---|---|---|---|
annotation |
注解过滤器,该过滤器需要指定一个注解名,如lee.AnnotationTest |
||
assignable |
类名过滤器,该过滤器直接指定一个Java类。 |
||
regex |
正则表达式过滤器,该过滤器指定一个正则表达式,匹配该正则表达式的Java类将满足该过滤规则,如org\.example\.Default.*。 |
||
aspectj |
Aspectj过滤器,如org.example..* Service+。 |
||
| # 程序示例 # | |||
|
例如,下面配置文件指定所有以Chinese结尾的类、以Axe结尾的类都将被当成Spring Bean处理。
beans.xml
1 |
|