Bean的自动检测

在spring实战四中,使用在Spring中增加<context:annotation-config>的方式告诉Spring,我们打算使用基于注解的自动装配,希望Spring特殊对待我们所定义的Bean里的某一组注解,并使用这些注解指导Bean的装配。即使  <context:annotation-config>有助于完全消除Spring配置中的 <property>和<constructor-arg>元素,我们仍然需要使用<bean>元素显示定义Bean。

而在另一方面,Spring提供了自动检测功能,  <context:component-scan> 元素除了完成与<context:annotation-config>一样的工作外,还允许Spring自动检测Bean和定义Bean。这意味着不使用<bean>元素,Spring中的大多数或者所有Bean都能够实现定义和装配。

为了配置Spring自动检测,需要使用<context:component-scan>元素来代替<context:annotation-config>元素:

复制代码

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan
  base-package="com.springinaction.springidol">
</context:component-scan>
</beans>

复制代码

<context:component-scan>元素会扫描指定的包及其子包,并查找出能够自动注册为Spring Bean的类。base-package属性标识了<context:component-scan>元素所扫描的包。

如何知道哪些类需要注册为Spring Bean呢?

1. 为自动检测标注Bean

默认情况下,<context:component-scan>查找使用构造型(stereotype)注解所标注的类,这些特殊的注解如下:

* @Component 通用的构造型注解,标识该类为spring组件

* @Controller 标识将该类定义为spring MVC 控制器

* @Repository 标识将该类定义为数据仓库(在使用数据库的时候可以用到该注解)

* @Service 标识将该类定义为服务

* 使用@Component标注的任意自定义注解

例如,我们的上下文中仅仅包含eddie和guitar两个Bean。可以配置<context:component-scan>元素并使用@Component注解标注Instrumentlist和Guitar类,从而消除显示的<bean>定义。

首先,使用@Component注解标注Guitar类:

复制代码

package com.springinaction.springidol;
import org.springframework.stereotype.Component;
@Component
public class Guitar implements Instrument {
public void play() {
System.out.println("Strum strum strum");
}
}

复制代码

Spring 扫描com.springinaction.springidol包时,会发现使用@Component注解所标注的Guitar,并自动将它注册为Spring Bean。Bean的ID默认为无限定类名。在这种场景下,Guitar的ID为guitar。

现在再标注Instrumentlist类:

复制代码

package com.springinaction.springidol;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component("eddie")
public class Instrumentalist implements Performer {
// ...
}

复制代码

在这种场景下,指定了一个Bean ID作为@Component注解的参数。该Bean的ID不是默认类的名称,而是显示命名为eddie。

2. 过滤组件扫描

<context:component-scan>在如何扫描获得候选Bean方面非常灵活,通过为<context:component-scan>配置<context:include-filter>和/或者<context:exclude-filter>子元素,我们可以随意调整扫描行为。

考虑一个问题:如何基于注解让<context:component-scan>自动注册所有实现Instrument接口的类?

我们替换掉基于注解的组件扫描策略,再增加一个包含过滤器来要求<context:component-scan>自动注册所有的Instrument实现类,如下所示:

<context:component-scan
base-package="com.springinaction.springidol">
<context:include-filter type="assignable"
expression="com.springinaction.springidol.Instrument"/>
</context:component-scan><context:include-filter

<context:include-filter>的type和expression属性一起协作来定义组件扫描策略。我们还可以选择下面任意一种过滤器。

除了使用<context:include-filter>告知<context:component-scan>哪些类需要注册为Spring Bean以外,还可以使用<context:exclude-filter>告知<context:component-scan>哪些类不需要注册为Spring Bean。例如下面所示,除了使用自定义@SkipIt注解的类,其他所有的Instrument实现都需要注册为Spring Bean,如下所示:

复制代码

<context:component-scan
base-package="com.springinaction.springidol">
<context:include-filter type="assignable"
expression="com.springinaction.springidol.Instrument"/>
<context:exclude-filter type="annotation"
expression="com.springinaction.springidol.SkipIt"/>
</context:component-scan>

复制代码

当对<context:component-scan>应用过滤器时,可以有无限的过滤可能。但是我们会发现默认的基于注解的过滤策略是最经常用到的。

怀有希望!!

发布了12 篇原创文章 · 获赞 0 · 访问量 2145

猜你喜欢

转载自blog.csdn.net/Kuzma_/article/details/103504313