第二章 bean装配

Spring配置的可选方案

  1.XML中进行显式配置。
  2.在Java中进行显式配置。
  3.隐式的bean发现机制和自动装配。

自动化装配bean

  Spring从两个角度来实现自动化装配:
    组件扫描component scanning) : Spring会自动发现应用上下文中所创建的bean
    自动装配autowiring) : Spring自动满足bean之间的依赖。

创建可被发现的bean

package soundsystem;

public interface CompactDisc {
    public void play();
}
package soundsystem;

import org.springframework.stereotype.Component;

@Component
public class SgtPeppers implements CompactDisc {

    private String title = "Sgt.Pepper's Lonely Hearts Club Band";
    private String artist = "The Beatles";

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

    }

}

@ComponentScan注解启用了组件扫描

package soundsystem;

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

@Configuration
@ComponentScan
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"
    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>

运行:

package soundsystem;

import org.junit.Assert;
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=CDPlayerConfig.class)
public class CDtest {

    @Autowired
    private CompactDisc cd;

    @Test
    public void cdShouldNotNull() {
        Assert.assertNotNull(cd);
        cd.play();
    }

}

 

为组件扫描的bean命名

  Spring应用上下文中所有的bean都会给定一个ID。 在前面的例子中, 尽管我们没有明确地为SgtPeppersbean设置ID, 但Spring会根据类名为
  其指定一个ID。 具体来讲, 这个bean所给定的IDsgtPeppers, 也就是将类名的第一个字母变为小写
  如果想为这个bean设置不同的ID, 你所要做的就是将期望的ID作为值传递给@Component注解。 比如说, 如果想将这个bean标识
  为lonelyHeartsClub, 那么你需要将SgtPeppers类的@Component注解配置为如下所示:

  还有另外一种为bean命名的方式, 这种方式不使用@Component注解, 而是使用Java依赖注入规范(Java Dependency Injection) 中所提供
  的@Named注解来为bean设置ID

package soundsystem;

import org.springframework.stereotype.Component;
//import javax.inject.Named;

@Component("lonelyHeartsClub")
//@Named("lonelyHearsClub")
public class SgtPeppers implements CompactDisc

设置扫描的基础包

package soundsystem;

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

@Configuration
@ComponentScan("soundsystem")
@ComponentScan(basePackages = "soundsystem")
@ComponentScan(basePackages = {"soundsystem","video"})
@ComponentScan(basePackageClasses = {CDPlayer.class,SgtPeppers.class})
public class CDPlayerConfig {

}

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

  通过自动装配, 将一个CompactDisc注入到CDPlayer之中

package soundsystem;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class CDPlayer implements MediaPlayer {

    private CompactDisc cd;

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

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

}

 @Autowired注解不仅能够用在构造器上, 还能用在属性的Setter方法上。 比如说, 如果CDPlayer有一个setCompactDisc()方法, 那么可
 以采用如下的注解形式进行自动装配:

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

@Autowired注解可以用在类的任何方法上。 假设CDPlayer类有一个insertDisc()方法, 那
@Autowired能够像在setCompactDisc()上那样, 发挥完全相同的作用:

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

如果没有匹配的bean, 那么在应用上下文创建的时候, Spring会抛出一个异常。 为了避免异常的出现, 你可以将@Autowiredrequired
性设置为false

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

required属性设置为false时, Spring会尝试执行自动装配, 但是如果没有匹配的bean的话, Spring将会让这个bean处于未装配的状态。
但是, 把required属性设置为false时, 你需要谨慎对待。 如果在你的代码中没有进行null检查的话, 这个处于未装配状态的属性有可能会
出现NullPointerException

通过JAVA代码装配bean

创建配置类

package soundsystem;

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

@Configuration
public class CDPlayerConfig {

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

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

看起来, CompactDisc是通过调用sgtPeppers()得到的, 但情况并非完全如此。 因为sgtPeppers()方法上添加了@Bean注解, Spring
将会拦截所有对它的调用, 并确保直接返回该方法所创建的bean, 而不是每次都对其进行实际的调用。
比如说, 假设你引入了一个其他的CDPlayerbean, 它和之前的那个bean完全一样

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

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

在这里,cdPlayer()方法请求一个CompactDisc作为参数。 当Spring调用cdPlayer()创建CDPlayerbean的时候, 它会自动装配一
CompactDisc到配置方法之中。 然后, 方法体就可以按照合适的方式来使用它。 借助这种技术, cdPlayer()方法也能够
CompactDisc注入到CDPlayer的构造器中, 而且不用明确引用CompactDisc@Bean方法。

    @Bean
    public CDPlayer cdPlayer(CompactDisc compactDisc) {
        return new CDPlayer(compactDisc);
    }

通过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">
</beans>

  声明一个简单的<bean>

<bean class="soundsystem.SgtPeppers"/>

  因为没有明确给定ID, 所以这个bean将会根据全限定类名来进行命名。 在本例中, beanID将会是soundsystem.SgtPeppers#0。 其
  中, #0是一个计数的形式, 用来区分相同类型的其他bean。 如果你声明了另外一个SgtPeppers, 并且没有明确进行标识, 那么它自动得到
  的ID将会是soundsystem.SgtPeppers#1

  借助id属性, 为每个bean设置一个你自己选择的名字:

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

  借助构造器注入初始化bean

<bean class="soundsystem.CDPlayer">
    <constructor-arg ref="CompactDisc"/>
</bean>

 

设置属性

 

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

 

JavaConfig中引用XML配置

  @Import(CDConfig.class)

  @ImportResource

package soundsystem;

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

@Configuration
public class CDConfig {

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

 

package soundsystem;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportResource;

@Configuration
@Import(CDConfig.class)
@ImportResource("classpath:bean.xml")
public class CDPlayerConfig {

    @Bean
    public CDPlayer cdPlayer(CompactDisc compactDisc) {
        return new CDPlayer(compactDisc);
    }
}

XML配置中引用JavaConfig

<bean class="soundsystem.CDConfig"/>

<?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 class="soundsystem.CDConfig"/>

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

 <import resource="cdplayer-config.xml"/>

<?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 class="soundsystem.CDConfig"/>

    <import resource="cdplayer-config.xml"/>
</beans>

 


 

 

 

posted @ 2018-01-23 19:32  110528844  阅读(129)  评论(0编辑  收藏  举报