zoukankan      html  css  js  c++  java
  • Spring 通过Java代码装配bean

    1. 背景

    书接上文Spring自动化装配bean

    尽管在很多场景下通过组件扫描和自动装配实现Spring的自动化扫描配置是更为推荐的方式,但在有些情况下自动化扫描的方案行不通,如想要将第三方库中的组件装配到自己的应用中。在这种情况下必须通过显示 装配的方式。

    显示装配有两种可选方案:Java和XML。JavaConfig是更好的方案:更强大、类型安全并对重构友好。因他就是Java代码。

    2. 代码 & 解说

    接口: CompactDisc.java

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

    接口: MediaPlayer.java

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

    SgtPeppers.java

    package soundsystem;
    
    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);
      }
    
    }

    注:区别与自动转配,这里去掉了@compenent注解

    CDPlayer.java

    package soundsystem;
    import org.springframework.beans.factory.annotation.Autowired;
    
    public class CDPlayer implements MediaPlayer {
      private CompactDisc cd;
    
      @Autowired
      public CDPlayer(CompactDisc cd) {
        this.cd = cd;
      }
    
      @Override
      public void play() {
        cd.play();
      }
    }

    借助JavaConfig实现注入

    CDPlayerConfig.java

    package soundsystem;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class CDPlayerConfig {
      
      @Bean
      public CompactDisc compactDisc() {
        return new SgtPeppers();
      }
    
      @Bean
      public CDPlayer cdPlayer(CompactDisc compactDisc) {
        return new CDPlayer(compactDisc);
      }
    }

    注:区别与自动装配,这里去掉了@ComponentScan注解,而是显式的声明了Bean。@Bean注解告诉了Spring上下文这个方法会将返回一个对象,该对象要注册为Spring应用上下文中的bean,方法体重包含了最终产生bean实例的实现逻辑。

    测试CDPlayerTest.java

    package soundsystem;
    
    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 CDPlayerTest {
    
      @Autowired
      private MediaPlayer player;
    
      @Test
      public void play() {
        player.play();
      }
    }

    3. 深入了解JavaConfig

    别于上面代码中的实现方式,还可以这样配置JavaConfig

    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
      public CDPlayer cdPlayer() {
        return new CDPlayer(sgtPeppers());
      }
    }

    cdPlayer没有使用默认的构造函数,而是调用了CompactDisc对象。看起来是通过调用sgtPeppers()得到的,实际不是这样的。原因是sgtPeppers方法是上添加了@Bean注解,Spring将会拦截所有对它的调用,而是直接返回方法所创建的bean,而不是每次都对其进行实际的调用。以下为证

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

    假如每次都调用sgtPeppers()方法,那么每个CDPlayer实例将会有一个特有的SgtPepper实例,但实际上是相同的实例。

    相比于前面代码中的声明方式,还是推荐上述代码中的方式,那样更容易理解。如

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

    这种方法不用明确引用@Bean方法也能将CompactDisc注入到CDPlayer的构造器中。这种方式是引用其他bean的最佳方式,它不需要要求将CompactDisc必须在JavaConfig中声明。

  • 相关阅读:
    中国剩余定理及拓展
    20191128-1 总结
    获取动态图
    弹球游戏设计
    作业要求 20191121-1 每周例行报告
    作业要求 20191114-1 每周例行报告
    对现组内成员的感谢
    作业要求 20191107-1 每周例行报告
    20191031-1 每周例行报告
    作业要求 20191024-1每周例行报告
  • 原文地址:https://www.cnblogs.com/kaituorensheng/p/6984234.html
Copyright © 2011-2022 走看看