Spring Annotation(二)
?
?
由于?office
?Bean 被注释掉了,所以 Spring 容器中将没有类型为?Office
?的 Bean 了,而 Boss 的?office
?属性标注了?@Autowired
,当启动 Spring 容器时,异常就产生了。
当不能确定 Spring 容器中一定拥有某个类的 Bean 时,可以在需要自动注入该类 Bean 的地方可以使用@Autowired(required = false)
,这等于告诉 Spring:在找不到匹配 Bean 时也不报错。来看一下具体的例子:
清单 11. 使用 @Autowired(required = false)
?
我们在 Spring 容器中配置了两个类型为?Office
?类型的 Bean,当对 Boss 的?office
?成员变量进行自动注入时,Spring 容器将无法确定到底要用哪一个 Bean,因此异常发生了。
Spring 允许我们通过?@Qualifier
?注释指定注入 Bean 的名称,这样歧义就消除了,可以通过下面的方法解决异常:
清单 13. 使用 @Qualifier 注释指定注入 Bean 的名称
?
<context:annotationconfig/> 将隐式地向 Spring 容器注册AutowiredAnnotationBeanPostProcessor
、CommonAnnotationBeanPostProcessor
、PersistenceAnnotationBeanPostProcessor
以及?equiredAnnotationBeanPostProcessor
?这 4 个 BeanPostProcessor。
在配置文件中使用 context 命名空间之前,必须在 <beans> 元素中声明 context 命名空间。
虽然我们可以通过?@Autowired
?或?@Resource
?在 Bean 类中使用自动注入功能,但是 Bean 还是在 XML 文件中通过 <bean> 进行定义 —— 也就是说,在 XML 配置文件中定义 Bean,通过?@Autowired
?或?@Resource
?为 Bean 的成员变量、方法入参或构造函数入参提供自动注入的功能。能否也通过注释定义 Bean,从 XML 配置文件中完全移除 Bean 定义的配置呢?答案是肯定的,我们通过 Spring 2.5 提供的?@Component
?注释就可以达到这个目标了。
下面,我们完全使用注释定义 Bean 并完成 Bean 之间装配:
清单 20. 使用 @Component 注释的 Car.java
?
这里,所有通过 <bean> 元素定义 Bean 的配置内容已经被移除,仅需要添加一行 <context:component-scan/> 配置就解决所有问题了——Spring XML 配置文件得到了极致的简化(当然配置元数据还是需要的,只不过以注释形式存在罢了)。<context:component-scan/> 的 base-package 属性指定了需要扫描的类包,类包及其递归子包中所有的类都会被处理。
<context:component-scan/> 还允许定义过滤器将基包下的某些类纳入或排除。Spring 支持以下 4 种类型的过滤方式,通过下表说明:
表 1. 扫描过滤方式
过滤器类型说明
?
值得注意的是 <context:component-scan/> 配置项不但启用了对类包进行扫描以实施注释驱动 Bean 定义的功能,同时还启用了注释驱动自动注入的功能(即还隐式地在内部注册了?AutowiredAnnotationBeanPostProcessor
和?CommonAnnotationBeanPostProcessor
),因此当使用 <context:component-scan/> 后,就可以将 <context:annotation-config/> 移除了。
默认情况下通过?@Component
?定义的 Bean 都是 singleton 的,如果需要使用其它作用范围的 Bean,可以通过@Scope
?注释来达到目标,如以下代码所示:
清单 24. 通过 @Scope 指定 Bean 的作用范围
package com.baobaotao;import org.springframework.context.annotation.Scope;…@Scope("prototype")@Component("boss")public class Boss { …}
?
这样,当从 Spring 容器中获取?boss
?Bean 时,每次返回的都是新的实例了。
?采用具有特殊语义的注释
Spring 2.5 中除了提供?@Component
?注释外,还定义了几个拥有特殊语义的注释,它们分别是:@Repository
、@Service
?和?@Controller
。在目前的 Spring 版本中,这 3 个注释和?@Component
?是等效的,但是从注释类的命名上,很容易看出这 3 个注释分别
和持久层、业务层和控制层(Web 层)相对应。虽然目前这 3 个注释和?@Component
?相比没有什么新意,但
?Spring 将在以后的版本中为它们添加特殊的功能。所以,如果 Web 应用程序采用了经典的三层分层结构的话,
最好在持久层、业务层和控制层分别采用?@Repository
、@Service
?和?@Controller
?对分层中的类进行注释,
而用?@Component
?对那些比较中立的类进行注释。
注释配置和 XML 配置的适用场合
是否有了这些 IOC 注释,我们就可以完全摒除原来 XML 配置的方式呢?答案是否定的。有以下几点原因:
JdbcTemplate
、SessionFactoryBean
?等),注释配置将无法实施,此时 XML 配置是唯一可用的方式。@Transaction
?事务注释,使用 aop/tx 命名空间的事务配置更加灵活和简单。所以在实现应用中,我们往往需要同时使用注释配置和 XML 配置,对于类级别且不会发生变动的配置可以优先考虑注释配置;而对于那些第三方类以及容易发生调整的配置则应优先考虑使用 XML 配置。Spring 会在具体实施 Bean 创建和 Bean 注入之前将这两种配置方式的元信息融合在一起。
小结
Spring 在 2.1 以后对注释配置提供了强力的支持,注释配置功能成为 Spring 2.5 的最大的亮点之一。合理地使用 Spring 2.5 的注释配置,可以有效减少配置的工作量,提高程序的内聚性。但是这并不意味着传统 XML 配置将走向消亡,在第三方类 Bean 的配置,以及那些诸如数据源、缓存池、持久层操作模板类、事务管理等内容的配置上,XML 配置依然拥有不可替代的地位。
?