应用依赖注入的正确 Spring Boot 方式是什么

桑德_M

我目前正在开发一个 Spring Boot 应用程序,该应用程序以以下方式将一些 bean 连接在一起(高度简化的示例):

@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");     
    }   
}

然而,实际 bean 需要的配置和设置比此处显示的要多得多,并且在使用内部 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 框架的最正确方法是什么。

问题

鉴于 Player 和 Shoes bean 需要的不仅仅是一行初始化(多个设置、对其他 bean 的多个依赖等),设计和连接它们的最佳方法是什么?

编辑 - 基于建议

添加了一个配置类来捆绑 bean:

@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));
        });

    }       
}

Re 使用相同的第一个 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
帕维乌·杰维克

正如 Andriy Slobodyanyk 提到的,一种解决方案是更改 Player 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");
    }
}

如果以上还不够(因为你提到真实案例场景更复杂)另一种选择是使用 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();
            }
        });

    }
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

Spring boot 应用程序中 oracle maven 依赖的兼容版本是什么?

来自分类Dev

用静态内容部署Spring Boot应用程序的正确方法是什么

来自分类Dev

通过 maven for Spring Boot 应用程序为 AWS Beanstalk 创建 .ebextensions 的正确方法是什么

来自分类Dev

Spring进行依赖注入的方式

来自分类Dev

与当前 spring boot 2.0.0M3 配合使用的正确 spring cloud 版本是什么

来自分类Dev

Spring Boot的默认内存设置是什么?

来自分类Dev

spring boot中的bootstrap yaml是什么

来自分类Dev

用Java创建微服务的正确路径是什么?Spring Boot或OSGI

来自分类Dev

Gradle:指定最终 spring-boot jar 文件的正确方法是什么?

来自分类Dev

在Spring Boot应用程序中安排任务的最佳方法是什么

来自分类Dev

在 Spring Boot Web 应用程序中编译 LESS 文件的推荐方法是什么?

来自分类Dev

基于 Spring Boot 构造函数的依赖注入不起作用

来自分类Dev

辅助类型依赖注入在 spring boot 中不起作用

来自分类Dev

Spring Boot以编程方式延迟启动Web应用程序

来自分类Dev

Spring-Boot如何正确注入javax.validation.Validator

来自分类Dev

启动一个简单的非基于Web的Java应用程序的官方spring boot方法是什么?

来自分类Dev

如果您在 docker 中使用了 Spring Boot 应用程序,那么使用 SSL 的最佳方法是什么

来自分类Dev

spring boot gradle文件中的“ tag :: ...”语法是什么?

来自分类Dev

在Spring Boot中处理异常的最佳方法是什么?

来自分类Dev

依赖注入在 PHP 中的正确方式 - Laravel

来自分类Dev

Spring Boot中的依赖管理

来自分类Dev

Spring-boot 依赖问题

来自分类Dev

什么可以从 Spring Boot 应用程序中排除?

来自分类Dev

使用Spring和Scala进行多依赖注入的语法是什么?

来自分类Dev

Spring Data / Spring Boot循环依赖问题?

来自分类Dev

关机的正确终端方式是什么?

来自分类Dev

正确或错误的表达方式是什么

来自分类Dev

在ServiceStack API应用程序中使用的正确的“按请求”简单注入器生活方式是什么?

来自分类Dev

如何正确配置我的 Spring Boot 应用程序?

Related 相关文章

  1. 1

    Spring boot 应用程序中 oracle maven 依赖的兼容版本是什么?

  2. 2

    用静态内容部署Spring Boot应用程序的正确方法是什么

  3. 3

    通过 maven for Spring Boot 应用程序为 AWS Beanstalk 创建 .ebextensions 的正确方法是什么

  4. 4

    Spring进行依赖注入的方式

  5. 5

    与当前 spring boot 2.0.0M3 配合使用的正确 spring cloud 版本是什么

  6. 6

    Spring Boot的默认内存设置是什么?

  7. 7

    spring boot中的bootstrap yaml是什么

  8. 8

    用Java创建微服务的正确路径是什么?Spring Boot或OSGI

  9. 9

    Gradle:指定最终 spring-boot jar 文件的正确方法是什么?

  10. 10

    在Spring Boot应用程序中安排任务的最佳方法是什么

  11. 11

    在 Spring Boot Web 应用程序中编译 LESS 文件的推荐方法是什么?

  12. 12

    基于 Spring Boot 构造函数的依赖注入不起作用

  13. 13

    辅助类型依赖注入在 spring boot 中不起作用

  14. 14

    Spring Boot以编程方式延迟启动Web应用程序

  15. 15

    Spring-Boot如何正确注入javax.validation.Validator

  16. 16

    启动一个简单的非基于Web的Java应用程序的官方spring boot方法是什么?

  17. 17

    如果您在 docker 中使用了 Spring Boot 应用程序,那么使用 SSL 的最佳方法是什么

  18. 18

    spring boot gradle文件中的“ tag :: ...”语法是什么?

  19. 19

    在Spring Boot中处理异常的最佳方法是什么?

  20. 20

    依赖注入在 PHP 中的正确方式 - Laravel

  21. 21

    Spring Boot中的依赖管理

  22. 22

    Spring-boot 依赖问题

  23. 23

    什么可以从 Spring Boot 应用程序中排除?

  24. 24

    使用Spring和Scala进行多依赖注入的语法是什么?

  25. 25

    Spring Data / Spring Boot循环依赖问题?

  26. 26

    关机的正确终端方式是什么?

  27. 27

    正确或错误的表达方式是什么

  28. 28

    在ServiceStack API应用程序中使用的正确的“按请求”简单注入器生活方式是什么?

  29. 29

    如何正确配置我的 Spring Boot 应用程序?

热门标签

归档