Spring装配Bean的主要方式总结

这里写图片描述

Spring装配Bean有三种主要方式:自动装配、基于Java显示配置和基于XML显示配置。建议使用的是自动装配,一是简单快捷,二是显示配置维护麻烦。但是显示配置在有些场景下是必须的或者高效的,例如想讲第三方库的组件装配到自己的应用中,肯定不能去把第三方的组件类加上注释;或者需要维护别人写的代码,但是他用的是显示配置,如果不了解就无从下手,所以也应该了解spring的显示配置方式。

1. 自动装配

用CD和CD播放器举例:spring如何将一个CD类,通过配置装配到CD播放器中。
这里写图片描述

@Component声明组件

通过UML图可以看到,需要做的是把SgtPeppers注入到CDplayer中,所以将这两个类看成是一个组件,spring通过一番操作将他们组合在一起,无论如何将他们组合在一起,第一步我们先把他们都声明成spring能认识的组件,肯定不会错。spring声明组件用的就是@Component。

@Component
public class SgtPeppers implements CompactDisc {

    private String title = "White Horse";
    private String artist = "Talyor Swift";

    @Override
    public void play() {
        System.out.println("Playing " + title + " by " + artist);
    }
}

@Autowired自动装配注解

和SgtPeppers声明成为组件略微不同的是,CDplayer需要将SgtPeppers注入到其中。所以需要有一个让spring知道,SgtPeppers需要注入到CDplayer,我们常用的注入方式有构造器注入或者是setter方法注入,spring注入的方式也一样,只是通过@Autowired注解让其注入自动完成。

@Component
public class CDPlayer implements MediaPlayer {

    private CompactDisc cd;

    @Autowired(required=false)
    public CDPlayer(CompactDisc cd){
        this.cd = cd;
    }

    @Override
    public void play() {
        cd.play();
    }

}

要注意的是:@Autowired可以注释任何方法,有了这个注释spring会试图创建一个注释了的bean,但如果没有找到bean则会报出异常为了避免异常将@Autowired(required=false)添加false,但添加false避免该异常后,如果没有进行null检查会报NullPointExeception。

@ComponentScan扫描组件

刚才创建了两个组件,但是组件扫描默认是不开启的,所以需要我们显示地配置一下spring,先尝试用一个java类来定义spring的装配规则。

/** 
  * 如果没有其他配置,spring通过以下配置会扫描CDPlayerConfig
  * 所处类下的包的所有子包
/** 
@Configuration
@ComponentScan
public class CDPlayerConfig {

}

但如果想要扫描多个基础包呢?

//扫描多个基础包
@Configuration
@ComponentScan(basePackages={"soundsystem","video"})
public class CDPlayerConfig {
}

上述方法扫描的基础包采用String类型的包名,类型不安全,改进采用包下的一个组件类:

@Configuration
@ComponentScan(baseClasses={CDPlayer.class,DVDPlayer.class})
public class CDPlayerConfig {
}

当然你可能还会想到,通过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:c="http://www.springframework.org/schema/c"
  xmlns:p="http://www.springframework.org/schema/p"
  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.xsd">

  <context:component-scan base-package="soundsystem" />

</beans>

2. JavaConfig装配Bean

当需要将第三方库中的组件装配到应用中时,是没有办法在他的类上添加@Component或者@Autowired的,所以可以采用javaxml,先来看java代码配置。

利用java进行配置,我们把用于配置spring的java类成为JavaConfig,他和普通的java类其实是没有多大区别的,但是作为一个配置类,最好遵循以下几个原则,当然不是强制的:

  1. JavaConfig放在同一个包下
  2. 配置代码不侵入业务代码

还是以上面的CD为例,原本的组件类不再申明为一个组件,去掉@Component,即假设他们是第三方库中的代码,我们无法添加注解

public class SgtPeppers implements CompactDisc {

    private String title = "White Horse";
    private String artist = "Talyor Swift";

    @Override
    public void play() {
        System.out.println("Playing " + title + " by " + artist);
    }
}

那么配置代码中就要做相应改变,配置代码去掉@ComponentScan,并且用@Bean来申明JavaBean

@Configuration
public class CDPlayerConfig {

    @Bean
    public CompactDisc sgtPeppers(){
        return new SgtPeppers();
    }

    /*@Bean
    public CDPlayer cdplayer(CompactDisc compactDisc){
        return new CDPlayer(compactDisc);
    }*/

    @Bean
    public CDPlayer cdplayer(){
        return new CDPlayer(sgtPeppers());
    }

}

这里Bean的注入有两种方法,上面注释掉的是通过参数注入,而下面没有注释的是通过调用方法注入,两种方法都可以但是通过参数注入更加直观,也更加常用。值得注意的是,@Bean的注解可以使用任何必要的Java功能来返回一个bean实例。

3. XML装配Bean

还是那句话,推荐使用自动装配和JavaConfig,但是不可避免会用到XML的方式进行spring的配置,因为我们会需要维护别人的代码啊。

XML申明一个Bean

<bean id="compactDisc" class="soundsystem.SgtPeppers" />

其中id是这个bean的别名,一般都会起别名,如果没有id属性,别名默认为“soundsystem.SgtPeppers#0”,#0用于计算区别于其他的Bean。

如果申明一个Bean的过程中需要注入其他的对象,或者对象,可以采用两种方法:一种是采用构造器注入,一种是采用方法注入,两两组合所以有四种实例化的方式:

1. 构造器注入对象

<bean id="cdPlayer" class="soundsystem.CDPlayer">
   <constructor-arg ref="compactDisc" />
</bean>

还可以采用c名称空间,引入名称空间是为了简写

<bean id="cdPlayer"
        class="soundsystem.CDPlayer"
        c:_-ref="compactDisc" />

2. 构造器注入普通属性

和注入对象稍微有一点差别

  <bean id="compactDisc" class="soundsystem.BlankDisc"
       <constructor-arg value="Sgt. Pepper's Lonely Hearts Club Band" />
       <constructor-arg value="The Beatles" />
  </bean>

名称空间写法

  <bean id="compactDisc"
        class="soundsystem.BlankDisc"
        c:_0="Sgt. Pepper's Lonely Hearts Club Band"
        c:_1="The Beatles">
  </bean>

3. 方法注入对象

前面使用构造器注入,这里用setter方法注入,如果JavaBean是这样的,自动使用setter进行注入

public class CDPlayer implements MediaPlayer {

    private CompactDisc cd;

    @Autowired
    public void CompactDisc(CompactDisc compactDisc){
        this.CompactDisc = CompactDisc;
    }

    @Override
    public void play() {
        cd.play();
    }

}

相应的XML用property属性来配置,和使用构造器注入是一样的

<bean id="cdPlayer" class="soundsystem.CDPlayer">
   <property name="compactDisc" ref="compactDisc" />
</bean>

当然也可以使用p名称空间

<bean id="cdPlayer" class="soundsystem.CDPlayer">
   <p:compactDisc-ref="compactDisc" />

4. 方法注入普通值

其实都以类似的方法,用P名称空间演示

  <bean id="compactDisc"
        class="soundsystem.BlankDisc"
        p:title="Sgt. Pepper's Lonely Hearts Club Band"
        p:artist="The Beatles">
  </bean>

5. 注入集合不能用名称空间

名称空间可以简写,但是名称空间不能注入集合,集合的注入是这样的

  <bean id="compactDisc"
        class="soundsystem.BlankDisc"
        c:_0="Sgt. Pepper's Lonely Hearts Club Band"
        c:_1="The Beatles">
    <constructor-arg>
      <list>
        <value>Sgt. Pepper's Lonely Hearts Club Band</value>
        <value>With a Little Help from My Friends</value>
        <value>Lucy in the Sky with Diamonds</value>
        <value>Getting Better</value>
        <value>Fixing a Hole</value>
        <!-- ...other tracks omitted for brevity... -->
      </list>
    </constructor-arg>
  </bean>

4. 混合配置

最后是将JavaConfig的配置同XML配置相互结合如何使用,因为他们是互不排斥的

1. 在javaConfig中引用xml配置

所以会有两个需要装配的bean,一个是用过javaConfig装配,另一个是通过xml装配,然后我们用一个JavaConfig装配在一起

JavaConfig装配的Bean

@Configuration
public class CDConfig {
  @Bean
  public CompactDisc compactDisc() {
    return new SgtPeppers();
  }
}

Xml装配的Bean,XML文件名为cd-config.xml

<bean id="compactDisc"
        class="soundsystem.BlankDisc"
        c:_0="Sgt. Pepper's Lonely Hearts Club Band"
        c:_1="The Beatles">
    <constructor-arg>
      <list>
        <value>Sgt. Pepper's Lonely Hearts Club Band</value>
        <value>With a Little Help from My Friends</value>
        <value>Lucy in the Sky with Diamonds</value>
        <value>Getting Better</value>
        <value>Fixing a Hole</value>
        <!-- ...other tracks omitted for brevity... -->
      </list>
    </constructor-arg>
  </bean>

通过@ImportResource注解,在javaConfig中引用xml文件
@Import引入JavaConfig文件

@Configuration
@Import(CDPlayerConfig.class)
@ImportResource("classpath:cd-config.xml")
public class SoundSystemConfig {

}

2. 在xml中引用JavaConfig配置

前面是使用@ImportResource注解,那么在XML中加载JavaConfig配置其实也类似:

<import resouse="cd-congig.xml"/>
<bean class="soundsystem.CDConfig">

介绍完了,给自己做个学习笔记,如有不对敬请指正。

原文地址:https://www.cnblogs.com/shuiyj/p/13185256.html