如果我们不使用xml配置文件来配置Bean实例,那么我们只能指望Spring会自动搜索某些路径下的Java类,并将这些Java类注册成Bean实例。
Spring要求程序员显式指定搜索哪些路径下的Java类,Spring将会把合适的Java类全部注册成Spring Bean。现在的问题是:Spring怎么知道应该把哪些Java类当成Bean类处理呢?这就需要使用Annotation了,Spring通过使用一些特殊的Annotation来标注Bean类。Spring提供了如下几个Annotation来标注Spring Bean。
Annotation名称 | 说明 |
@Component | 标注一个普通的Spring Bean类。 |
@Controller | 标注一个控制器组件类。 |
@Service | 标注一个业务逻辑组件类。 |
@Repository | 标注一个DAO组件类。 |
在Spring的未来版本中,@Controller、@Service和@Repository也许还能携带更多语义,因此如果需要在JavaEE应用中使用这些标注时,尽量考虑使用@Controller、@Service和@Repository来代替通用的@Component标注。
指定了某些类可作为Spring Bean类使用后,最后还需要让Spring搜索指定路径,此时需要在Spring配置文件中导入context Scheme,并指定一个简单的搜索路径。
注意现在使用Annotation,工程除了spring.jar 和 commons-logging.jar,还需要添加一个common-annotations.jar,其路径为spring开发包下的lib--->j2ee--->common-annotations.jar
Axe.java :
public interface Axe {
public String chop();
}
SteelAxe.java :
@Component
public class SteelAxe implements Axe {
@Override
public String chop() {
return "钢斧砍柴真快";
}
}
StoneAxe.java :
@Component
public class StoneAxe implements Axe {
@Override
public String chop() {
return "石斧砍柴真慢";
}
}
Person.java :
public interface Person {
public void useAxe();
}
Chinese.java :
@Component
public class Chinese implements Person {
private Axe axe;
public void setAxe(Axe axe) {
this.axe = axe;
}
@Override
public void useAxe() {
System.out.println(axe.chop());
}
}
bean.xml :
<?xml version="1.0" encoding="UTF-8"?>
<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"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<context:component-scan base-package="com.bean"/>
</beans>
Test.java :
public class Test {
public static void main(String[] args) {
ApplicationContext ctx=new ClassPathXmlApplicationContext("bean.xml");
System.out.println(Arrays.toString(ctx.getBeanDefinitionNames()));
}
}
运行Test.java,控制台输出:
[
steelAxe, stoneAxe, chinese,
org.springframework.context.annotation.internalCommonAnnotationProcessor,
org.springframework.context.annotation.internalAutowiredAnnotationProcessor,
org.springframework.context.annotation.internalRequiredAnnotationProcessor
]
每个使用了@Component标注的Java类都将作为Spring的Bean类。
从上面程序的运行结果来看,Spring容器中三个Bean实例的名称分别为chinese、steelAxe和stoneAxe,之所以叫这些名称,是因为在这种基于Annotation的方式下,Spring采用约定的方式来为这些Bean实例指定名称,这些Bean实例的名称默认是Bean类的首字母小写,其他部分不变。
当然,Spring也允许在使用@Component标注时指定Bean实例的名称:
@Component("axe")
public class SteelAxe implements Axe{
//codes here
}
上面程序中指定该Bean实例的名称为axe。
在默认情况下,Spring会自动搜索所有以@Component、@Controller、@Service和@Repository标注的Java类,并将它们当成Spring Bean来处理。
除此之外,我们还可通过为<component-scan.../>元素添加<include-filter.../>或<exclude-filter.../>子元素来指定Spring Bean类,只要位于指定路径下的Java类满足这种规则,即使这些java类没有使用任何Annotation标注,Spring一样会将它们当成Bean类来处理。
<include-filter.../>元素用于指定满足该规则的Java类会被当成Bean类处理。<exclude-filter.../>元素用于指定满足该规则的Java类不会被当成Bean类处理。使用这两个元素时都要求指定如下两个属性:
① type:指定过滤器类型。
② expression:指定过滤器所需要的表达式。
Spring内建支持如下4种过滤器:
① annotation:Annotation过滤器,该过滤器需要指定一个Annotation名,如lee.AnnotationTest
② assignable:类名过滤器,该过滤器直接指定一个Java类。
③ regex:正则表达式过滤器,该过滤器指定一个正则表达式,匹配该正则表达式的Java类将满足该过滤规则,如org\.example\.Default.*。
④ aspectj:AspectJ过滤器,如org.example..*Service+。
例如下面的配置文件指定所有以Chinese结尾的类,以Axe结尾的类都将被当成Spring Bean处理。
<context:component-scan base-package="org.crazyit.app.service">
<context:include-filter type="regex" expression=".*Chinese"/>
<context:include-filter type="regex" expression=".*Axe"/>
</context:component-scan>