2017-04-22 113 views
0

正確的春天啓動的方式我目前工作的一個春天啓動的應用程序,電線一些豆子一起以下列方式(大量簡化的例子):什麼是應用依賴注入

@Component 
@Order(0) 
public class PlayingFieldByBeans implements CommandLineRunner { 

    @Override 
    public void run(String... arg0) throws Exception { 
     List<String> names = new ArrayList<>(); 
     names.add("Alex"); 
     names.add("Benedict"); 
     names.add("Chloe"); 

     System.out.println("Printing from lazy beans variant: "); 
     names.forEach(n -> { 
      System.out.println(player(n)); 
     }); 

    } 

    @Bean 
    @Lazy 
    public Player player(String name) { 
     return new Player(name, shoes());  
    } 

    @Bean 
    @Lazy 
    private Shoes shoes() { 
     return new Shoes("Adidas");  
    } 
} 

然而,實際的豆類,需要更多的配置和設置,比使用內部Lazy Bean方法時在PlayingFieldByBeans類中需要相當多的代碼行。因此,我創建使用Component註釋一起佈線它以不同的方式:

@Component 
@Order(1) 
public class PlayingFieldByComponents implements CommandLineRunner {  

    @Autowired 
    private PlayerComponent playerComponent; 

    @Override 
    public void run(String... arg0) throws Exception { 
     List<String> names = new ArrayList<>(); 
     names.add("Alex"); 
     names.add("Benedict"); 
     names.add("Chloe"); 

     System.out.println("Printing from component variant: "); 
     names.forEach(n -> { 
      System.out.println(playerComponent.player(n)); 
     }); 

    }  
} 

的PlayerComponent類看起來是這樣的:

@Component 
public class PlayerComponent { 

    @Autowired 
    private ShoesComponent shoesComponent; 

    public Player player(String name) { 
     return new Player(name, shoesComponent.shoes()); 
    } 
} 

的ShoesComponent是非常相似的PlayerComponent類。

爲了可維護性和TDD的目的,我不確定在這裏使用spring框架最合適的方式是什麼。

問題

鑑於球員和鞋豆類需要更多的則只是一條線初始化(多重設置,其他豆類等多個依賴),什麼是設計和它們連接的最佳方式?

編輯 - 根據建議

增加的配置類捆綁豆:

@Configuration 
public class BeanConfiguration { 

    @Bean 
    @Lazy 
    public Player player(String name) { 
     return new Player(name, shoes());  
    } 

    @Bean 
    @Lazy 
    public Shoes shoes() { 
     return new Shoes("Adidas");  
    } 

} 

和匹配的執行類:

@Component 
@Order(2) 
public class PlayingFieldByConfiguration implements CommandLineRunner { 

    @Autowired 
    private BeanConfiguration beanConfiguration; 

    @Override 
    public void run(String... arg0) throws Exception { 
     List<String> names = new ArrayList<>(); 
     names.add("Alex"); 
     names.add("Benedict"); 
     names.add("Chloe"); 

     System.out.println("Printing from component variant: "); 
     names.forEach(n -> { 
      System.out.println(beanConfiguration.player(n)); 
     }); 

    }  
} 

重新使用相同的第一個bean ,所以它似乎沒有創建一個新的

Printing from component variant: 
Player name: Alex has shoes of brand: Adidas 
Player name: Alex has shoes of brand: Adidas 
Player name: Alex has shoes of brand: Adidas 
+0

你看看'@ Configuration'組件在春天嗎?看起來像這將是你需要的東西,把所有的bean初始化代碼放在那裏。 –

+0

用您的建議更新了問題,謝謝 –

+2

默認情況下Bean是單例,即使看起來「返回新」創建多個對象。使用@Scope(BeanDefinition.SCOPE_PROTOTYPE) –

回答

1

一個解決辦法是到(以後如果我們要創造不同的品牌和鞋)由舍甫琴科Slobodyanyk提到改變球員bean的範圍

@Configuration 
public class BeanConfiguration { 

    @Bean 
    @Lazy 
    @Scope(BeanDefinition.SCOPE_PROTOTYPE) 
    public Player player(String name) { 
     return new Player(name, shoes()); 
    } 

    @Bean 
    @Lazy 
    public Shoes shoes() { 
     return new Shoes("Adidas"); 
    } 
} 

如果上面是不夠的(既然你提到真實的情況是更compilcated)另一種選擇是使用FactoryBean的

public class PlayerFactoryBean implements FactoryBean<Player> { 

    private String name; 
    private Shoes shoes; 

    public void setName(String name) { 
     this.name = name; 
    } 

    public void setShoes(Shoes shoes) { 
     this.shoes = shoes; 
    } 

    @Override 
    public Player getObject() throws Exception { 
     //initialization logic goes here 
     System.out.println("Creating bean using factory"); 
     return new Player(name, shoes); 
    } 

    @Override 
    public Class<Player> getObjectType() { 
     return Player.class; 
    } 

    @Override 
    public boolean isSingleton() { 
     return false; 
    } 
} 

@Configuration 
public class BeanConfiguration { 

    @Bean 
    @Lazy 
    public Shoes shoes() { 
     return new Shoes("Adidas"); 
    } 

    @Bean 
    public PlayerFactoryBean playerFactoryBean(){ 
     PlayerFactoryBean pfb = new PlayerFactoryBean(); 
     pfb.setShoes(shoes()); 
     return pfb; 
    } 
} 

@Component 
@Order(2) 
public class PlayingFieldByConfiguration implements CommandLineRunner { 

    @Autowired 
    private PlayerFactoryBean factoryBean; 

    @Override 
    public void run(String... arg0) throws Exception { 
     List<String> names = new ArrayList<>(); 
     names.add("Alex"); 
     names.add("Benedict"); 
     names.add("Chloe"); 

     System.out.println("Printing from component variant: "); 
     names.forEach(n -> { 
      try { 
       factoryBean.setName(n); 
       System.out.println(factoryBean.getObject()); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     }); 

    } 
}