美文网首页
最小化Spring XML配置

最小化Spring XML配置

作者: Tu9oh0st | 来源:发表于2018-12-19 21:48 被阅读0次

    Spring提供了几种技巧,可以帮助我们减少XML的配置数量。

    • 自动装配(autowiring)有助于减少甚至消除配置<property>元素和<constructor-arg>元素,让Spring自动识别如何装配Bean的依赖关系。
    • 自动检测(autodiscovery)比自动装配更进了一步,让Spring能够自动识别哪些类需要被装配成Spring Bean,从而减少对<bean>元素的使用。

    当自动装配和自动检测一起使用时,它们可以显著减少Spring的XML配置数量。通常只需要配置少量的几行XML代码,而无需知道在Spring的应用上下文中究竟有多少Bean。

    自动装配Bean属性

    自动装配(autowiring)

    4种类型的自动装配

    当涉及自动装配Bean的依赖关系时,Spring有多种处理方式。因此,Spring提供了4种各具特色的自动装配策略。

    • byName——把与Bean的属性具有相同名字(或者ID)的其他Bean自动装配到Bean的对应属性中。如果没有跟属性的名字相匹配的Bean,则该属性不进行装配。
    • byType——把与Bean的属性具有相同类型的其他Bean自动装配到Bean的对应属性中。如果没有跟属性的类型相匹配的Bean,则该属性不被装配。
    • constructor——把与Bean的构造器入参具有相同类型的其他Bean自动装配到Bean构造器的对应入参中。
    • autodetect——首先尝试使用constructor进行自动装配。如果失败,再尝试使用byType进行自动装配。

    byName自动装配

    举个栗子:

    <bean id="kenny2"
          class="com.springinaction.springidol.Instrumentalist">
    <property name="song" value="Jingle Bells" />
        <property name="instrument" ref="saxophone" />
    </bean>
    

    在这里,我们使用<property>元素显式装配了Kenny的instrument属性。假设使用<bean>元素在定义萨克斯(saxophone)时,把Bean的id属性设置为instrument:

    <bean id="instrument"
            class="com.springinaction.springIdol.Saxphone" />
    

    在本示例中,萨克斯(saxophone)Bean的id属性与Keeny Bean的instrument属性的名字是一样的。通过配置autowire属性,Spring就可以利用此信息自动装配kenny的instrument属性

    <bena id="kenny"
          class="com.springinaction.springidol.Instrumentlist"
          autowire="byName">
    <property name="song" value="Jingle Bells"/>
    </bena>
    

    byName自动装配遵循一项约定:为属性自动装配ID与该属性的名字相同的Bena。通过设置autowire属性为byName,Spring将特殊对待kenny的所有属性,为这些属性寻找与其名字相同的Spring Bean。在这里,Spring会发现instrument属性可以通过setter注入来进行自动装配。

    使用byName自动装配的缺点是需要假设Bean的名字与其他Bean的属性的名字一样。

    byType自动装配

    byType自动装配的工作方式类似于byName自动装配,只不过不再是匹配属性的名字而是检查属性的类型。当我们尝试使用byType自动装配时,Spring会寻找哪一个Bean的类型与属性的类型相匹配。

    constructor自动装配

    如果要通过构造器注入来配置Bean,那我们可以移除<constructor-arg>元素,由Spring在应用上下文中自动选择Bean注入到构造器入参中。

    例如:

    <bean id="duke"
          class="com.springinaction.springidol.PoeticJuggler"
          autowire="constructor"
          />
    

    上述声明告诉Spring去审视PoeticJuggler的构造器,并尝试在Spring配置中寻找匹配PoeticJuggler某一个构造器所有入参的Bean。

    最佳自动装配

    如果想自动装配Bean,但是又不能决定该使用那一种类型的自动装配。现在不必担心了,我们可以设置autuwire属性为autodetect,由Spring来决定。例如

    <bean id="duke"
          class="com.springinaction.springidol.PoeticJuggle"
          autowire="autodetect"/>
    

    当配置一个Bean的autowire属性为autodetect时,Spring将首先尝试使用constructor自动装配,如果没有发现与构造器相匹配的Bean时,Spring将尝试使用byType自动装配。

    默认自动装配

    default-autowire

    混合使用自动装配和显式装配

    使用注解装配

    从Spring2.5开始,最有趣的一种装配Spring Bean的方式是使用注解自动装配Bean的属性。使用注解自动装配与在XML中使用autowire属性自动装配并没有太大差别。但是使用注解方式允许更细粒度的自动装配,我们可以选择性地标注某一属性来对应其应用自动装配。

    Spring容器默认禁止注解装配。所以,在使用基于注解的自动装配前,我们需要在Spring配置中启用它。最简单的启用方式是使用Spring的context命名空间配置中的<context:annotation-config />元素。

    <context:annotation-config />元素告诉Spring我们打算使用基于注解的自动装配。一旦配置完成,我们就可以对代码添加注解,标识Spring应该为属性、方法和构造器进行自动装配。

    Spring3支持几种不同的用于自动装配的注解:

    • Spring自带的@Autowired注解
    • JSR-330的@Inject注解
    • JSR-250的@Resource注解

    使用@Autowired

    假设我们希望使用@Autowired让Spring自动装配乐器演奏家(Instrumentalist)Bean的instrument属性。则可以对setInstrument()方法进行标注,如下

    @Autowired
    public void setInstrument(Instrument instrument){
        this.instrument = instrument;
    }
    

    当Spring发现我们对setInstrument()方法使用了@Autowired注解时,Spring就会尝试对该方法执行byType自动装配。@Autowired也可以用于装配Bean的引用和标注构造器。

    可选的自动装配

    默认情况下,@Autowired具有强契约特征,其所标注的属性或参数必须是可装配的。如果没有Bean可以装配到@Autowired所标注的属性或参数中,自动装配就会失败(抛出令人讨厌的NoSuchBeanDefinitionException)。这可能是我们所期望的处理方式——当自动装配无法完成时,让Spring尽早失败,远胜于以后抛出异常。

    属性不一定非要装配,null值也是可以接受的。在这种场景下,可以通过设置@Autowired的required属性为false来配置自动装配是可选的。

    @Autowired(required=false)
    private Instrument instrument;
    

    在这里,Spring将尝试装配instrument属性,但是如果没有查找到与之匹配的类型为Instrument的Bean,应用就不会发生任何问题,而instrument属性的值会设置为null。

    限定歧义性的依赖

    为了帮助@Autowired鉴别出哪一个Bean才是我们所需要的,我们可以配合使用Spring的@Qualifier注解。

    例如,为了确保Spirng为eddie Bean选择吉他(guitar)来演奏,即使有其他Bean也可以装配到instrument属性中,但我们可以使用@Qualifier来明确指定名为guitar的Bean:

    @Autowired
    @Qualifier("guitar")
    private Instrument instrument;
    

    如上所示,@Qualifier注解将尝试注入ID为guitar的Bean。

    借助@Inject实现基于标准的自动装配

    和@Autowired一样,@Inject可以用来自动装配属性、方法和构造器;与@Autowired不同的是,@Injet没有required属性。因此,@Inject注解所标注的依赖关系必须存在,如果不存在,则会抛出异常。

    例如,我们有一个KnifeJuggler类需要注入一个或多个Knife的实例。假设Knife Bean的作用域声明为prototype,下面的KnifeJuggler的构造器将获得5个Knife Bean:

    private Set<Knife> knives;
    
    @Inject
    public KnifeJuggler(Provider<Knife> knifeProvider){
        knives = new HashSet<Knife>();
        for(int i=0;i<5;i++){
            knives.add(knifeProvider.get());
        }
    }
    

    KnifeJuggler将获得一个Provider<Knife>,而不是在构造器中获得一个Knife实例。这个时候,只有provider被注入进去;在调用provider的get()方法之前,实际的Knife对象并没有被注入。在这个示例中,get()方法被调用了5次。因为Knife Bean的作用域为prototype,所以knife的Set集合将被赋予5个不同的Knife对象。

    限定@Inject所标注的属性

    @Named注解的工作方式非常类似于Spring的@Qualifier,正如我们在这里所看到的:

    @Inject
    @Named("guitar")
    private Instrument instrument;
    

    在注解注入中使用表达式

    @Value注解尽管易于使用,但我们很快就会发现,它同样具有威力。我们可以通过@Value直接标注某个属性、方法或者方法参数,并传入一个String类型的表达式来装配属性。例如:

    @Value("Eruption")
    private String song;
    

    在这里,我们为String类型的属性装配了一个String类型的值。但是传入@Value的String类型的参数只是一个表达式——它的结算结果可以是任意类型,因此@Value能够标注任意类型的属性。

    自动检测Bean

    <context:component-scan>元素除了完成了与<context:annotation-config>一样的工作,还允许Spring自动检测Bean和定义Bean。

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

    为自动检测标注Bean

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

    • @Component ——通用的构造型注解,标识该类为Spring组件。
    • @Controller——标识将该类定义为SpringMVC controller。
    • @Repository——标识将该类定义为数据仓库
    • @Service——标识将该类定义为服务。
    • 使用@Component标注的任意自定义注解。

    过滤组件扫描

    通过为<context:component-scan>配置<context:include-filter>和/或者<context:exclude-filter>子元素,我们可以随意调整扫描行为。

    过滤器类型 描述
    annotation 过滤器扫描使用指定注解所标注的那些类,通过expression属性指定要扫描的注解
    assignable 过滤器扫描派生于expression属性所指定类型的那些类
    aspectj 过滤器扫描与expression属性所指定的AspectJ表达式所匹配的那些类
    custom 使用自定义的org.springframework.core.type.TypeFilter实现类,该类由expression
    regex 过滤器扫描类的名称与expression属性所指定的正则表达式匹配的那些类

    相关文章

      网友评论

          本文标题:最小化Spring XML配置

          本文链接:https://www.haomeiwen.com/subject/gpmskqtx.html