如果我们不使用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>