当前位置: 首页 > 知识库问答 >
问题:

spring中的动态依赖注入

商绍元
2023-03-14
@Component
class Example {
    private SpringBean1 bean1;
    private SpringBean2 bean2;
    private String dynamicDependancy;

    @Autowired
    public Example(SpringBean1 bean1, SpringBean2 bean2, String dynamicDepedency) {
        this.bean1 = bean1;
        this.bean2 = bean2;
        this.dynamicDepedency = dynamicDepedency;
    }
}
@Component
class ExampleFactory {
    private SpringBean1 bean1;
    private SpringBean2 bean2;

    @Autowired
    public ExampleFactory(SpringBean1 bean1, SpringBean2 bean2) {
        this.bean1 = bean1;
        this.bean2 = bean2;
    }

    public Example from(String dynamicDependency) {
        return new Example(bean1, bean2, dynamicDependency);
    }

    static class Example {
        private SpringBean1 bean1;
        private SpringBean2 bean2;
        private String dynamicDependancy;

        public Example(SpringBean1 bean1, SpringBean2 bean2, String 
            dynamicDependancy) {
            this.bean1 = bean1;
            this.bean2 = bean2;
            this.dynamicDependancy = dynamicDependancy;
        }
    }
}

谢谢你。

更新:我找到了另一个解决方案,并在另一个帖子中发布了答案:https://stackoverflow.com/a/52021965/2580829

共有1个答案

段干茂实
2023-03-14

您的基本方法是使用Spring注入的工厂,然后公开创建example实例的方法,因此基本上是正确的。如果您想让Spring使用它的现代特性透明地完成这项工作,可以使用@configuration类结合查找方法注入,从单例范围的bean按需创建example实例。

首先,配置类:

@Configuration
public class DemoConfiguration {
    @Autowired IFooBean fooBean;
    @Autowired IBarBean barBean;

    @Bean()
    @Scope("prototype")
    Example newExample(String name) {
        return new Example(fooBean, barBean, name);
    }
}

除了newexamplename参数之外,这里应该没有什么太令人惊讶的地方。您可以像我在上面所做的那样自动生成容器能够满足的依赖关系(foobeanbarbean),但是由于配置类的实例是像Spring创建的任何其他bean一样创建的,所以您还可以使用任何其他机制:将ObjectFactoryObjectProvider注入配置中,使其实现ApplicationContextAware,甚至为它们使用查找方法注入。如果您需要避免foobeanbarbean像它们被autowed到配置bean中那样被提前初始化,那么这将非常有用。

不要忘记将工厂方法的范围设置为“prototype”,否则Spring将只返回您创建的第一个bean,即使您为name传递了不同的值。

example的实现本身与您的问题中的实现类似:

public class Example {
    IFooBean fooBean;
    IBarBean barBean;
    String name;

    public Example(IFooBean fooBean, IBarBean barBean, String name) {
        System.out.printf("%s(fooBean=%s, barBean=%s, name=%s)\n", this, fooBean, barBean, name);
        this.fooBean = fooBean;
        this.barBean = barBean;
        this.name = name;
    }
}

然后,在实际需要example实例时,使用@lookup注入工厂方法:

public interface IUsesExample {
    void doThing();
}

@Component
public class UsesExample implements IUsesExample {
    @Lookup
    protected Example getExample(String name) {return null;};

    public void doThing() {
        System.out.printf("%s.doThing(getExample() = %s)\n", this, getExample("aaa"));
        System.out.printf("%s.doThing(getExample() = %s)\n", this, getExample("bbb"));
    }
}

使用下面的Spring Boot小应用程序对此进行测试:

@SpringBootApplication
public class DemoApplication {
    @Autowired IUsesExample usesExample;

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @PostConstruct
    void run() {
        usesExample.doThing();
    }
}

给出以下输出:

com.example.demo.FooBean@fd46303
com.example.demo.BarBean@6a62689d
com.example.demo.Example@66629f63(fooBean=com.example.demo.FooBean@fd46303, barBean=com.example.demo.BarBean@6a62689d, name=aaa)
com.example.demo.UsesExample$$EnhancerBySpringCGLIB$$68b994e8@6c345c5f.doThing(getExample() = com.example.demo.Example@66629f63)
com.example.demo.Example@6b5966e1(fooBean=com.example.demo.FooBean@fd46303, barBean=com.example.demo.BarBean@6a62689d, name=bbb)
com.example.demo.UsesExample$$EnhancerBySpringCGLIB$$68b994e8@6c345c5f.doThing(getExample() = com.example.demo.Example@6b5966e1)

即:

    null
 类似资料:
  • 我正在编写一个应用程序,该应用程序与一个数据库通信,获取其他数据库的凭据,并连接到其他数据库。它使用在运行时构造的数据源和实体管理器工厂来执行此操作。 如果我想使用Spring Data Repositories,我想我需要自动连接它们,因此它们必须是Spring Beans。 如果在对第一个数据库运行查询之前没有构造的DataSource,我如何使用Spring Data?

  • 问题内容: 我仍然是Angularjs的新手。我想在控制器中动态注入服务(我创建的)的依赖项。 但是,当我对具有依赖项的服务进行编码时,出现此错误: 错误:未知提供程序:$ windowProvider <-$ window <-base64 这是控制器的代码。 此代码有效: 此代码不起作用: 另一个问题是服务与控制器位于同一模块中。如果模块具有依赖项,则无法使用(我的模块配置中具有$ route

  • 我有一个正在使用jar的项目a,比如(其中B是在项目a中用作依赖项的另一个项目),现在有一个(类似于缓存),它在映射中保存所需的所有数据。这个映射bean被project(在我的项目中作为包含)使用,即B来读取缓存属性,但我无法这样做,有什么帮助吗? 项目B的webapp-config.xml 上面的bean b2必须在外部项目B中使用(作为jar包含在我的项目A中)。 但我得到了 任何帮助都将不

  • 我遇到了依赖注入周期问题。我请求重新设计建议。提前谢谢。 错误描述:应用程序上下文中某些bean的依赖关系形成一个循环: 这是两个班 第一类: 第二类:

  • 问题内容: 我能够使用RestTemplate并将其自动连线。但是我想将我与其余模板相关的代码部分移到另一个类中,如下所示: 在另一堂课上我称之为: 我是Spring和Dependency Injection术语的新手。我的变量为null并引发异常。我该怎么解决(我不知道它与我使用 关键字有关)吗? 问题答案: 使用不适用于依赖项注入。你没有被注入,因为wbin不是由Spring管理的。 你必须自

  • 问题内容: Spring在以下方面很好地支持JUnit:使用和注释,事情看起来非常直观 该测试将能够在Eclipse&Maven中正确运行。我想知道TestNG是否有类似的东西。我正在考虑迁移到“下一代”框架,但没有找到与Spring测试匹配的对象。 问题答案: 它也可以与TestNG一起使用。