Automatically wiring beans

  Spring attacks automatic wiring from two angles:

    Component scanning—Spring automatically discovers beans to be created in the application context

    Autowiring—Spring automatically satisfies bean dependencies.


 

  Working together, component scanning and autowiring are a powerful force and can help keep explicit configuration to a minimum.

  The CD provides a nice illustration of how DI works. CD players are of little value unless you insert (or inject) a CD into them. You could say that a CD player depends on a CD to do its job.

  To bring this illustration to life in Spring, let’s establish the concept of a CD in Java. The following listing shows CompactDisc, an interface that defines a CD.

package cn.dt.spring.wiringBeans.autoWired.soundsystem;

public interface CompactDisc {
    void play();
}

You still need an implementation of CompactDisc, though. In fact, you could have several CompactDisc implementations. In this case, you’ll start with one: the SgtPeppers class, as shown in the next listing.

package cn.dt.spring.wiringBeans.autoWired.soundsystem;

import org.springframework.stereotype.Component;

/**
 * \@Component. This simple annotation identifies this class as a component class 
 * and serves as a clue to Spring that a bean should be created for the class. 
 * @author anuo
 *
 */
/*
 *  All beans in a Spring application context are given an ID. What may not have been
    apparent from the previous example is that although you didn’t explicitly give the
    SgtPeppers bean an ID, it was given one derived from its class name. Specifically, the
    bean was given an ID of sgtPeppers by lowercasing the first letter of the class name.
    If you’d rather give the bean a different ID, all you have to do is pass the desired ID
    as a value to the @Component annotation. For example, if you wanted to identify the
    bean as lonelyHeartsClub, then you’d annotate the SgtPeppers class with @Component
    like this:
 */
//@Component
@Component("lonelyHeartsClub")
public class SgtPeppers implements CompactDisc {
    private String title = "Sgt. Pepper's Lonely Hearts Club Band";
    private String artist = "The Beatles";
    public void play() {
        System.out.println("Playing " + title + " by " + artist);
    }

}

  What you should take note of is that SgtPeppers is annotated with @Component. This simple annotation identifies this class as a component class and serves as a clue to Spring that a bean should be created for the class. There’s no need to explicitly configure a SgtPeppers bean; Spring will do it for you because this class is annotated with @Component.

  Component scanning isn’t turned on by default, however. You’ll still need to write an explicit configuration to tell Spring to seek out classes annotated with @Component and to create beans from them. The configuration class in the following listing shows the minimal configuration to make this possible.

  

package cn.dt.spring.wiringBeans.autoWired.soundsystem;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/**
 * Component scanning isn’t turned on by default, however.
 *  You’ll still need to write an explicit configuration to tell Spring to seek out 
 *  classes annotated with /@Component and to create beans from them.
 *  /@Configuration 可以去掉,/@ComponentScan不能
 * @author anuo
 *
 */
@Configuration
@ComponentScan
/*
 * \@ComponentScan 参数:basePackages,basePackageClasses
 */
public class CDPlayerConfig {

}

  But for now, observe that CDPlayerConfig doesn’t explicitly define any beans itself. Instead, it’s annotated with @ComponentScan to enable component scanning in Spring.

  With no further configuration, @ComponentScan will default to scanning the same package as the configuration class. Therefore, because CDPlayerConfig is in the soundsystem package, Spring will scan that package and any subpackages underneath it, looking for classes that are annotated with @Component. It should find the CompactDisc class and automatically create a bean for it in Spring.

  Believe it or not, with only two classes created, you already have something that you can try out. To test that component scanning works, let’s write a simple JUnit test that creates a Spring application context and asserts that the CompactDisc bean is, in fact, created. CDPlayerTest in the next listing does precisely that.

  

package cn.dt.spring.wiringBeans.autoWired.soundsystem;

import static org.junit.Assert.*;

import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.StandardOutputStreamLog;
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;

/**
 * CDPlayerTest takes advantage of Spring’s SpringJUnit4ClassRunner to have a
 * Spring application context automatically created when the test starts. And
 * the /@ContextConfiguration annotation tells it to load its configuration from
 * the CDPlayerConfig class. Because that configuration class includes
 * /@ComponentScan, the resulting application context should include the
 * CompactDisc bean
 * 
 * @author anuo
 *
 */
@SuppressWarnings("deprecation")
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = CDPlayerConfig.class)
public class CDPlayerTest {
    @Rule
    public final StandardOutputStreamLog log = new StandardOutputStreamLog();
    @Autowired
    private CompactDisc cd;

    @Autowired
    private MediaPlayer player;

    @Test
    public void cdShouldNotBeNull() {
        assertNotNull(cd);
    }

    @Test
    public void play() {
        player.play();
        assertEquals("Playing Sgt. Pepper's Lonely Hearts Club Band" + " by The Beatles\n", log.getLog());
    }
}

  CDPlayerTest takes advantage of Spring’s SpringJUnit4ClassRunner to have a Spring application context automatically created when the test starts. And the @ContextConfiguration annotation tells it to load its configuration from the CDPlayerConfig class. Because that configuration class includes @ComponentScan, the resulting application context should include the CompactDisc bean.

  

package cn.dt.spring.wiringBeans.autoWired.soundsystem;

public interface MediaPlayer {

    void play();
}
package cn.dt.spring.wiringBeans.autoWired.soundsystem;

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

@Component
public class CDPlayer implements MediaPlayer {
  private CompactDisc cd;

  /*
   * Its constructor is annotated with @Autowired, indicating that 
   * when Spring creates the CDPlayer bean,40 CHAPTER 2 Wiring beans 
   * it should instantiate it via that constructor and pass in a bean 
   * that is assignable to CompactDisc.
   */
  /*
   * If there are no matching beans, Spring will throw an exception as the application
   * context is being created. To avoid that exception, 
   * you can set the required attribute on @Autowired to false:
   * \@Autowired(required=false)
   */
  @Autowired
  public CDPlayer(CompactDisc cd) {
    this.cd = cd;
  }

  /*
   * The @Autowired annotation’s use isn’t limited to constructors. 
   * It can also be used on a property’s setter method.
   *  For example, if CDPlayer had a setCompactDisc() method
   */
 /* @Autowired
  public void setCompactDisc(CompactDisc cd) {
      this.cd = cd;
  }*/
  
  public void play() {
    cd.play();
  }

}

 

@Component:在spring扫描的时候会扫描有@Component的类,如果@Component没带参数,则spring为将类型首字母小写后的名称那个作为bean的name.

@Configure:标明此class为配置类

@ComponentScan:扫描的范围,如果没有参数,默认是与次类同目录以及子目录下带有@Component/@Bean的类 参数:basePackages/basePackageClasses

@ContextConfiguration(classes = CDPlayerConfig.class) :标明从CDPlayerConfig加载配置

@RunWith(SpringJUnit4ClassRunner.class) :test开始时自动创建spring application context。

@Autowired:自动注入,可用于constructor 、setter以及field,可设置@Autowired(required=false)来保证在没有可注入的bean时启动不抛出异常,但是可能会在运行中抛出空指针异常。当有多个符合可注入的bean时,会抛出exception indicating ambiguity in selecting a bean for autowiring

 


 

 wiring bean via XML

 

 

 


  

posted on 2016-11-10 14:51  Achris  阅读(412)  评论(0编辑  收藏  举报