Spring装配Bean
Pawn Lv2

红豆骰子生南国,入骨相思知不知

装配Bean

Spring容器负责创建应用程序中的Bean并通过DI来协调对象之间的关系。当描述bean如何装配的时候,Spring具有非常大的灵活性,它提供三种主要的装配机制:

  • 在XML中进行显式配置
  • 在Java中显式配置
  • 隐式的bean发现机制和自动装配

1、自动化的装配Bean

Spring从两个角度实现自动化的装配:

  • 组件扫描 :Spring会自动发现应用上下文中所创建的Bean;
  • 自动装配: Spring自动满足bean之间的依赖;
创建可被发现的bean
public interface CompactDisc{
    void play();
}

需要一个CompactDisc的实现,实际上,CompactDisc接口可以有很多的实现。

@Component
public class sgtPeppers implements CompactDisc{
    private String title="Sgt.Perpper`s Lonly Heart Club Band";
    private String artist="The Beatles";

    public void play(){
        System.out.println("Playing"+title+"by"+"artist");
    }
}
  • @Component注解:表明该类会作为组件类,并告知Spring要为这个类创建bean,没必要再去显示配置SgtPepeer的bean。

此时Spring只需要开启扫描即可,但是Spring的扫描并不是默认开启的。@ComponentScan 注解配置Spring,命令它去寻找带有@Conmponent注解的类,并为其创建bean。

package com.panhao.Automatic_assembly;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan
public class CompactDiscConfiguration {

}

此时已经可以实现Bean的自动装配,添加测试类进行测试:

package com.panhao.Automatic_assembly;

import static org.junit.Assert.assertNotNull;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = CompactDiscConfiguration.class)
public class TestAutomatic {

    @Autowired
    private CompactDisc cd;

    @Test
    public  void cdShouldNotBeNull() {
        assertnotNull(cd);
    }
}
  • @ContextConfiguration告诉Spring在CompactDiscConfiguration.class中加载配置;
  • @ComponentScan表示开启自动扫描;
为组件扫描的bean命名

Spring上下文中所有的Bean的都会给定一个ID,如果明确的给定bean的ID,Spring会根据类名为其指定一个ID:将类名的第一个字母变成小写。如果想要为这个Bean设置不同的name,可以在@Component注解中进行设置:

@Component("lonlyHeartClub")
public class sgtPeppers implements CompactDisc{
    private String title="Sgt.Perpper`s Lonly Heart Club Band";
    private String artist="The Beatles";

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

还要另外一种给Bean命名的方式,使用@Named注解(Java 依赖注入规范(Java Dependency Injection))。

package com.panhao.Automatic_assembly;

import javax.inject.Named;



@Named("lonlyHeartClub")
public class SgtPepper implements CompactDisc {
    private String title="SgtPepper";
    private String artist="panhao";

    public void play() {
        // TODO Auto-generated method stub
        System.out.println("Playing" +title+"By" +artist);
    }

}

Spring支持将@Name作为@Component注解代替方案。两者之间有细微的差别,但是在大多数的情况下都可以互相替换。

设置组件扫描的包

@ComponentScan没有设置任何属性的时候,Spring会按照默认规则,它会以配置类所在的包作为基础包来扫描组件@componentScan中的value属性是用来设置basepackage的值:

package com.panhao.Automatic_assembly;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
//扫描com.panhao包下所有的文件
@ComponentScan(basepackages="com.panhao")
public class CompactDiscConfiguration {

}

basepackage可以配置多个包,形式为:@ComponentScan(basepackage={"com.panhao.Service","com.panhao.DI})

basepackages的值的类型是String,在代码重构的时候会带来错误的风险。@ComponentScan提供了basePackageClasses的属性,用来设置扫描类的,形式和basepackages一样的。

@ComponentScan(basePackageClass={CDPlayer.class,DVDPlayer.class})
通过bean添加注解实现自动装配

自动装配就是让Spring自动满足bean依赖的一种方法,在满足依赖的过程中,会在Spring应用上下文中寻找匹配某个bean需求的其他bean。

@Component
public class CDPlayer implements MediaPlayer{

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

    public void play(){
        cd.play();
    }
}
  • 在构造器上添加@Autowired注解,这表明在创建CDPlayer的bean的时候,会通过这个构造器进行实例化并且会传入一个可设置给CompactDisc类型的bean

@Autowired注解不仅能够用在构造器上,还能用在setter属性上。如果CDPlayer有一个CompactDisc()方法,那么可以采用以下的方式配置:

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

在Spring初始化bean之后,它会尽可能去满足bean的依赖。实际上setter()方法并没有什么不同,@Autowired注解可以用在类的任何方法上。

不管是构造器还、setter方法还是其他的方法,Spring就会尝试满足方法参数上所声明的依赖。假如有且只有一个bean匹配依赖的需求的话,那么这个bean不会被装配进来。如果没有匹配的bean,那么应用在上下文的时候,Spring会抛出一个异常。为了避免异常的出现,可以将@Autowired的required属性设置为false如果有多个bean都能满足依赖,Spring将会抛出一个异常,表明没有明确的指定要选择哪个bean进行自动装配。

@Name注解与@Component注解可以互换一样,@InjectJava依赖注入所提供的注解)也可以与@Autowired互换,虽有细微的不一样,但是多数的场景可以互换。

2、通过Java代码装配Bean

创建配置类
@Configuration
public class CDPlayerConfig{

}
  • 创建JavaConfig类的关键在于为其添加@Configuration注解。@Configuration注解表明这是一个配置类,该类该包含在Spring应用上下文中如何创建Bean的细节。
声明简单的bean
@Bean
public CompactDisc sgtPeppers(){
    return new CompactDisc
}
  • @Bean注解会告诉Spring这个方法返回一个对象,该对象要注册为Spring应用上下文中的bean。@Bean拥有属性name用来设置bean的名称。
在JavaConfig中实现注入
@Bean
public CDPlayer cdPlayed(){
    return new CDPlayer(sgtPeppers())
}

3、使用XML装配Bean

最简单的XML配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.3.xsd">

        <context:annotation-config></context:annotation-config>

        <bean id="testEditor" class="com.panhao.Automatic_assembly.test.TestEditor"></bean>


        <bean id="spellChecker" class="com.panhao.Automatic_assembly.test.SpellChecker"></bean>

</beans>
装配简单的Bean

<bean></bean>元素的标签的是和@Bean注解的作用是一致的。

<bean  class="soundsystem.SgtPepper"></bean>

此时一个最简单的声明Bean就完成了,(创建这个bean的类通过class属性来指定,并且要求使用全限定名),此处没有给出明确的ID,所以默认ID为:soundsystem.SgtPepper#0,其中#0是用来区分其它同类型的bean的。<bean />标签借助id属性对bean进行命名。

<bean id="sgtPepper" class="soundsystem.SgtPepper"></bean>
借助构造器注入初始化bean

在Spring中只有一种声明bean的方式,使用<bean />元素并指定class属性。Spring会从这里获取必要的信息来创建bean。

在XML声明DI的时候有多种配置方法可供选择:

  • <constructor-arg >元素
  • 使用Spring3.0所引入的c命名空间

在已经声明sgtPepper这个bean的条件下,使用<constructor-arg/>对CDplayer进行注入:

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

使用c命名空间的时候需要在顶部声明:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
           xmlns:c="http://www.springframeword.org/schema/c"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.3.xsd">

        <context:annotation-config></context:annotation-config>
    <bean id="sgtPepper" class="soundsystem.SgtPepper"></bean>

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

</beans>
  • c:cd-ref="compactDisc" :其中c表示命名空间前缀,cd表示构造器参数的名称;-ref表示注入bean的应用;compactDisc要注入的bean的ID。

    1. c命名是通过应用构造器参数的名称,需要在编译的时候,将调试标志保存在代码中,如果移除调试的标志,代码就无法正常的执行。
    • 使用参数的位置替代参数的名称

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

      由于XML中不允许数字作为属性的第一个字符,因此必须在前面添加一个下划线_作为前缀。

      当构造器只有一个参数的时候,可以连位置信息都不用给:

      <bean id="cdPlayer" class="soundsystem.CDPlayer" c:_-ref="compactDisc"></bean>
将字面量将配进bean中

假设CompactDisc拥有实现类:

public BlankDisc implements CompactDisc{

    private String title;
    private String artist;

    public BlankDisc(String title,String artist){
        this.titile=title;
        this.artist=artist;
    }
    public void play(){
        System.out.println("Playing "+title+" By "+artist);
    }
}

此时使用<constructor-arg/>装配的时候:

<bean id="blankDisc" class="soundsystem.BlankDisc">
    <constructor-arg value="Sgt Pepper Lonly Hearts Clubs Band" />
    <constructor-arg value="The Beatles" />
</bean>

使用c命名空间装配的时候:

<bean id="blankDisc" class="soundsystem.BlankDisc" 
      c:_title="Sgt Pepper Lonly Hearts Clubs Band"
      c:_artist="The Beatles">
</bean>
  • 装配字面量与装配引用的区别在于属性名中去掉了-ref的后缀
  • Post title:Spring装配Bean
  • Post author:Pawn
  • Create time:2020-04-14 21:24:15
  • Post link:https://panhao.work/2020/04/14/Spring装配Bean/
  • Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.