开启自动检测
开启自动检测Bean有两种方式:
XML配置
<context:annotation-config>虽然消除了<property>和<constructor-arg>元素,但我们仍需使用<bean>元素显示定义Bean。
<context:component-scan>除了完成与<context:annotation-config>一样的工作还可以自动检测Bean和定义Bean。在Spring XML中配置:
1 | <context:component-scan base-package="com.spring.entity"> |
base-package指定了扫描的路径。
Java配置
1 | import org.springframework.context.annotation.ComponentScan; |
@ComponentScan会扫描与该类相同包下的所有带有@Component注解的类。
如果想明确指出扫描路径,可以配置value:
1 | (basePackages="com.spring") |
也可以配置多个扫描路径:
1 | (basePackages={"com.spring.entity","com.spring.dao"}) |
除了指定扫描路径,我们也可以指定扫描的类型:
1 | (basePackageClasses={Piano.class,Guitar.class}) |
为自动检测标注Bean
注解类型:
@Component —— 通用的构造型注解,标识该类为Spring组件。
@Controller —— 标识将该类定义为Spring MVC Controller组件。
@Repository —— 标识将该类定义为数据仓库。
@Service —— 标识将该类定义为服务。
通过标注这些注解,Spring才知道哪些类要被注册为Spring Bean。如,使用@Component标注Guitar类:
1 |
|
Spring扫描com.spring.entity包时,会发现使用@Component注解所标注的Guitar,并自动将其注册为Spring Bean。Bean的ID默认为无限定首字母小写类名,也就是guitar。
我们也可以显式设定ID:
1 | ("kenny") |
也可以使用@Named("kenny")代替@Component("kenny"),但一般我们还是使用@Component("kenny")比较直观。
然后实例化kenny Bean:
1 | public class Play { |
输出:
1 | 唱:May Rain |
现在在XML中没有任何<bean>元素,也实现了和先前一样的效果。在这个过程中,遇到了两个问题:
1 | Exception in thread "main" org.springframework.beans.factory.BeanDefinitionStoreException: |
通过查阅资料,发现有位老外给出了解释:
Note that the Java 8 bytecode level (-target 1.8, as required by -source 1.8) is only fully supported as of Spring Framework 4.0. In particular, Spring 3.2 based applications need to be compiled with a maximum of Java 7 as the target, even if they happen to be deployed onto a Java 8 runtime. Please upgrade to Spring 4 for Java 8 based applications.
于是将jdk改为1.7版本。修改后又遇到异常:
1 | Exception in thread "main" java.lang.UnsupportedClassVersionError: |
原来是jdk版本和jvm版本不一致所致。右键项目–>properties–>java compiler –> Enable project specific settings –>将compiler compliance level设置为1.7,至此问题都解决了。
过滤组件扫描
<context:component-scan>默认扫描指定路径下通过@Component标注的Bean。假如现在我们只要把Instrument所派生的类注册为Spring Bean,我们不得不去查看所有java代码,一个一个的给Instrument派生类添加@Component注解,假如有第三方实现了Instrument,其源码我们还看不到,这时候添加@Component注解就变得非常困难甚至不可能。幸好,我们还可以给<context:component-scan>元素添加过滤行为:通过为其配置<context:include-filter>和<context:exclude-filter>子元素。比如:
1 | <context:component-scan base-package="com.spring.entity"> |
其中,过滤器类型有5种:
| 过滤器类型 | 描述 |
|---|---|
| annotation | 过滤器扫描使用指定注解所标注的那些类,通过expression属性指定要扫描的注解 |
| assignable | 过滤器扫描派生于expression属性所指定类型的那些类 |
| aspectj | 过滤器扫描与expression属性所指定的AspectJ表达式所匹配的那些类 |
| custom | 使用自定义的org.springframework.core.type.TypeFilter实现类,该类由expression 属性指定 |
| regex | 过滤器扫描类的名称与expression属性所指定的正则表达式所匹配的类 |
com.spring.entity.SkipIt自定义限定器:
1 | ({ElementType.FIELD,ElementType.PARAMETER,ElementType.TYPE}) |
com.spring.entity目录下有三个类派生于Instrument:Piano,Saxophone,Guitar。现在用@SkipIt标注Piano和Guitar类:
1 |
|
1 |
|
Saxophone不做任何标注:
1 | public class Saxophone implements Instrument{ |
实例化kenny,输出:
1 | 唱:May Rain |
非常方便!

