Spring 装配Bean

spring 装配bean

spring装配bean的三种机制

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

自动化装配bean

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

  • 组件扫描:Spring会自动发现应用上下文中所创建的bean
  • 自动装配:Spring自动满足bean之间的依赖

Spring中有4种类型的组件自动扫描注释类型

  • @Component – 指示自动扫描组件。
  • @Repository – 表示在持久层DAO组件。
  • @Service – 表示在业务层服务组件。
  • @Controller – 表示在表示层控制器组件。
开启自动组件扫描

1 xml显式配置

<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"
    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">

    <context:component-scan base-package="com.yiibai.customer" />

</beans>

2 注解式配置

@Configuration
@ComponentScan
public calss CDPlayerConfig(){

}

CDPlayerConfig中并没有显式地声明任何bean,只不过它是用来@ComponentScan注解,这个注解能够在spring中弃用组件扫描
如果没有其他配置的话,@ComponentScan默认会扫描域配置类相同的包

无论注解式配置或者xml显示配置,我们都可以明确地设置扫描的基础班

<!-- 使用Annotation自动注册Bean,只扫描@Controller -->
<!-- base-package 如果多个,用“,”分隔 -->
<context:component-scan base-package="com.digitalpublishing.sage.dc.controller" use-default-filters="false">
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
@ComponentScan(basePackages={"controller","service"})
创建可被发现的bean

创建POJO 加上注解@Component
组件扫描默认是不启用的,我们需要显示配置一下Spring,从而命令他去需找导游@Component注解的类
,并为其创建bean

通过为bean添加注解实现自动装配

@Autowired注解不仅能够用在构造器上,还能用在属性的Setter方法上
在spring初始化之后,它会尽可能去满足bean的依赖,不管是构造器,setter方法还是在其他的方法,spring都会尝试满足方法参数上所声明的依赖
假如有且只有一个bean匹配依赖需求的话,那么这个bean将会被装配进来
如果没有匹配的bean,那么在应用上下文创建的时候,spring会抛出一个以上,为了避免异常的出现,你可以将@Autoeired的required属性设置为false
但如果将required属性设置为false时,spring会尝试执行自动装配,但是如果没有匹配的bean的话,spring将会让这个bean处于未装配的状态.如果在你的代码中没有进行null检查的话,这个处于未装配状态的属性可能会导致空指针异常

尽管很多场景下通过组件扫描和自动装配实现spring的自动化配置是更为推荐的方式,但如果你想要将第三方库中的组件装配到你的应用总,在这种情况下,是没有办法在它的类上添加@Component和@Autowired注解的,因此就不能使用自动化装配的方案了

这种情况下,你必须要采用显式装配的方式,在显式配置的时候,有两种可选方案

  • java
  • xml

通过Java代码装配bean

进行显式配置是,JavaConfig是更好的方案,它更强大,类型安全并且对重构友好
因为它就是Java代码,就像应用程序中的其他Java代码一样
但JavaConfig与其他的Java代码又有所区别,JavaConfig是配置大妈,这意味着它不应该包含任何业务逻辑,JavaConfig也不应侵入到业务逻辑代码中,其应放到单独的保重,使它与其他的应用程序逻辑分离开来

创建配置类

创建配置类,为其添加@Configuration注解,@Configuration注解表明这个类是一个配置类,该类应该包含在spring应用上下文中如何创建bean的细节

声明简单的bean

要在JavaConfig中声明bean,我们需要编写一个方法,这个方法会创建所需类型的实例,然后给这个方法添加@Bean注解
@Bean注解会告诉spring这个方法将会返回一个对象,该对象要注册为spring应用上下文中的bean,方法体中包含了最终产生bean实例的逻辑

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

}

借助JavaConfig实现注入

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

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

}

cDPlayer()方法像sgtPeppers()方法一样,同样使用了@Bean注解,这表明这个方法会创建一个bean实例并将其注册到spring应用上下文中,所创建的beanID为cdPlayer,与方法的名字相同
cDPlayer()的方法体与sgtPeppers()稍微有些区别,在这里并没有使用默认的构造器构建实例,而是调用了需要传入CompactDisc对象的构建器来创建CDPlayer实例

看起来,CompactDisc是荣国调用sgtPeppers()得到的,但情况并非如此,因为sgtPeppers()方法上添加了@Bean注解,spring将会拦截所有对他的调用,并确保直接返回该方法所创建的bean,而不是每次都对其进行实际的调用

通过xml装配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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans.xsd
                http://www.springframework.org/schema/context">


</beans>

声明一个简单的

<bean id="demoController" class="soundsystem.CDPlayer" />

这里声明了一个很简单的bean,创建这个bean的类通过class属性来指定的,并且要使用全限定的类名

借助构造器注入初始化的bean

在springxml配置中,只有一种声明bean的方式:使用

xml声明DI时,具体到构造器注入,有梁总节本配置方案选择

  • 使用spring3.0所引入的c-命名空间
<bean id="cdPlayer" class="soundsystem.CDPlayer"
  <constructor-arg ref="copactDisc" />
</bean>

当spring遇到这个

c-命名空间
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:c="http://www.springframework.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.xsd">

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

也可以直接注入值

将字面量注入到构造器中

我们不止可以将对象的引用装配到依赖于它们的其他对象之中,而且可以用一个字面量值来配置对象
例如:

//POJO
public class BlankDisc {
  private String title;
  private String artist;

  public BlankDisc(String title,String artist){
    this.title = title;
    this.artist = artist;
  }

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

}


<bean id="cdPlayer" class="soundsystem.CDPlayer" >
  <constructor-arg value="sgt.Pepper's lonely hearts clue band" />
  <constructor-arg value="The Beatles" />
</bean>

使用value属性,通过该属性表明给定的值要以字面量的形式注入到构造器中

c-命名空间
第一种,引用构造器参数的名字

<bean id="demoController" class="soundsystem.CDPlayer" >
  <c:_title="sgt.Pepper's lonely hearts clue band" />
  <c:_artist=="The Beatles" />
</bean>

第二中,通过参数索引装配相同的字面量值

<bean id="demoController" class="soundsystem.CDPlayer" >
  <c:_0="sgt.Pepper's lonely hearts clue band" />
  <c:_1=="The Beatles" />
</bean>

xml不允许摸个元素的多个属性具有相同的名字,因此,如果有两个或更多的构造器参数的话,我们不能简单地使用下划线进行标识.但是如果只有一个构造参数的话,就可以

装配集合 c-命名空间无法作答
//POJO
public class BlankDisc {
  private String title;
  private String artist;
  private List<String> tracks;

  public BlankDisc(String title,String artist){
    this.title = title;
    this.artist = artist;
    this.tracks = tracks;
  }

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

<bean id="cdPlayer" class="soundsystem.CDPlayer" >
  <constructor-arg value="sgt.Pepper's lonely hearts clue band" />
  <constructor-arg value="The Beatles" />
  <constructor-arg><null/></constructor-arg>
</bean>

因为增加了一个tarcts属性,在声明bean的时候 我们必须给出声明,最简单的方法就是将列表设置为null,因为它是要给构造器参数,我们必须给出声明,所以采用上述方式传递null给他
但更好的解决办法是提供一个列表
例如:

<bean id="cdPlayer" class="soundsystem.CDPlayer" >
  <constructor-arg value="sgt.Pepper's lonely hearts clue band" />
  <constructor-arg value="The Beatles" />
  <constructor-arg>
    <list>
      <value>sgt.Pepper's lonely hearts clue band</value>
      <value>A</value>
      <value>B</value>
    </list>
  </constructor-arg>
</bean>

也可以用

<bean id="cdPlayer" class="soundsystem.CDPlayer" >
  <constructor-arg value="sgt.Pepper's lonely hearts clue band" />
  <constructor-arg value="The Beatles" />
  <constructor-arg>
    <list>
      <ref bean="sagtPepers"/>
      <ref bean="A"/>
      <ref bean="B"/>
    </list>
  </constructor-arg>
</bean>

设置属性 (setter注入)

<bean id="cdPlayer" class="soundsystem.CDPlayer" >
  <property name="compactDisc" ref="compactDisc" />
</bean>
//<property>元素为属性的setter方法提供的功能,与<constructor-arg>元素为构造器所提供的功能一样
//在本例中,它引用了ID为compactDisc的bean(通过ref属性),并将期注入到compactDisc属性中(通过setCompactDisc()方法).

猜你喜欢

转载自www.cnblogs.com/miye/p/9990104.html