2017-04-22 104 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(); 
      } 
     }); 

    } 
}