Spring自动检测Bean——Componet-Scan

一、自动检测

自动检测(autodiscovery) 让Spring能够自动识别哪些类需要被装配成SpringBean 从而减少在xml配置文件对 元素的使用。

注:自动检测和是否使用注解无关,它并不局限应用于注解方式的编程(包括注解自动装配bean以及注解注册bean)

第一步、标识用于装配的bean

要想把类标识成可用于@Autowired自动装配的bean的类,采用以下注解可实现:

@Component 通用的注解,可标注任意类为spring组件。
@Controller 标识将该类定义为spring MVC 控制器
@Repository 标识将该类定义为数据仓库(在使用数据库的时候可以用到该注解)
@Service 标识将该类定义为服务

上面的注解内部都是用@Component标注的,所以实际上可以在任何地方使用@Component, 但是为了表达更加清晰的设计意图,强烈建议根据不同情况使用不同的注解。

使用自动检测后扫描到的类,容器会将类名且第一个字母小写来作为bean的id

@Component
public class NotifyServiceByCellPhoneImpl implements NotifyService{
    @Override
    public void sendMessage(String message) {
        System.out.println("发送手机短信:"+message);
    }
}

在上面的例子中NotifyServiceByCellPhoneImpl的id将被设置为默认的notifyServiceByCellPhoneImpl

也可以在@Component注解中指定Bean的id</fon他》

@Component("notifyservice")
public class NotifyServiceByCellPhoneImpl implements NotifyService{
    @Override
    public void sendMessage(String message) {
        System.out.println("发送手机短信:"+message);
    }
}
第二步、开启自动扫描(将等待装配的bean注册进容器)

自动检测可以让Spring从指定的包中,自动扫描需要被装配到容器当中的bean。
开启自动扫描,需要在spring的配置文件当中配置如下的代码(可配置多条):

<context:component-scan base-package="twm.spring.start" />
<context:component-scan base-package="twm.spring.pojo" />

这样,spring会自动检测twm.spring.start包和twm.spring.pojo包中的所有标识可以被注册为spring bean的类。

同样要记得在xml文件添加context命名空间并指定schema:

<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:context="http://www.springframework.org/schema/context" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:c="http://www.springframework.org/schema/c" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-4.2.xsd">

<context:component-scan/>包含了自动注入的几个功能,因此当使用<context:component-scan/>后,可将上一篇自动装配用到的<context:annotation-config/>省去。

二、filter子标签

<context:component-scan>提供的两个子标签:<context:include-filter>和<context:exclude-filter>,它们分别代表引入和排除。

<context:include-filter>标签:

<context:component-scan base-package="twm.spring.start">
     <context:include-filter type="regex" expression="twm\.spring\.start\.*Impl" /> 
</context:component-scan>

这样在twm.spring.start包下所有名称以”Impl”结尾的类,都将被注册到容器中去。

<context:exclude-filter>标签:

<context:component-scan base-package="twm.spring.start">
        <context:exclude-filter type="regex" expression="twm\.spring\.start\.Test_*Impl" />        
</context:component-scan>

这样在twm.spring.start包下所有名称以”Test_”开头且以”Impl”结尾的类,都将被排除,不会注册到容器中去。

关于expression表达式的书写要注意两点:
1、可以采用完全限定名的方式(绝对路径),如上例中的:expression=“twm.spring.start.*Impl”,twm.spring.start.NotifyServiceByCellPhoneImpl
2、可以采用基于base-package包的方式(相对路径),如:

<context:component-scan base-package="twm.spring.start" >
     <context:include-filter type="regex" expression="\.*Impl" /> 
</context:component-scan>

<context:component-scan/>有个属性use-default-filters,将属性值设置为false,意即在base-package所有被标识了@Component和@Service等注解的Class不予注册到容器,权权交给filter子标签来决定。如果设为true,那就两种注册方式都包含了。

如果不想在类前面加@Component、@Service这些注解,又要让类被装配到容器中,可以使用filter子标签。
这样把NotifyServiceByCellPhoneImpl类前面的@Component去掉,它也能注册到容器中。使用<context:exclude-filter>则相反,把匹配的排除不给注册,剩下的全部注册到容器。

千万要注意控制注册到容器的包,不要出现注册多个同类型的bean,这样在注入时(byType)会出现错误。典型的现象就是,一个接口有多个实现,某个Bean需要注入这个接口的实现类,如果将接口的实现类一股脑注册到容器中,就会出问题。

在子标签中,出现了type这个属性。上面的例子用到了type=”regex”(常用)。在spring中,这里的type有五种可选项:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值