简体   繁体   English

Java Spring Bean 依赖注入,conditionalOnBean

[英]Java Spring Bean dependency injection, conditionalOnBean

Attempting to create a class that will be used by JavaConfig as a source of bean definitions.试图创建一个类,该类将被 JavaConfig 用作 bean 定义的源。

@Configuration
public class MyClass {
    @Bean
    @ConditionalOnProperty(name = "property")
    public A fuction1() {
       doSomething1(); // may return an exception
    }

    @Bean
    @ConditionalOnMissingBean(name = "fuction1")
    public A fuction2() {
        doSomething2();
    }

    @Bean
    public B fuction3(A a) {
        doSomething3(a);
    }
}

The third bean definition has the error "could not autowire. There is more than one bean of A type."第三个 bean 定义有错误"could not autowire. There is more than one bean of A type." How do I tell Spring to try to autowire the first A and if it is missing then to try the second A, ie following the conditional process described.我如何告诉 Spring 尝试自动装配第一个 A,如果它丢失,则尝试第二个 A,即遵循描述的条件过程。 Hopefully that makes sense.希望这是有道理的。 Thanks!谢谢!

You are defining two bean with same name hence, autowiring issue is obvious.您正在定义两个具有相同名称的 bean,因此,自动装配问题很明显。 Try using @Primary on the bean you want to give priority.尝试在要优先处理的 bean 上使用@Primary

How about this approach?这种方法怎么样?

@Configuration
public class MyClass {
    @Bean
    @ConditionalOnProperty(name = "property", havingValue="true")
    public A fuction1() {
       doSomething1(); // may return an exception
    }

    @Bean
    @ConditionalOnProperty(name = "property", havingValue="false")
    public A fuction2() {
        doSomething2();
    }

    @Bean
    public B fuction3(A a) {
        doSomething3(a);
    }
}

Maybe this config will be helpful:也许这个配置会有所帮助:

@Configuration
public class MyClass {
    @Bean
    @ConditionalOnProperty(name = "property")
    public A fuction1() {
        try {
            doSomething1(); // may return an exception
        } catch(Exception e) {
            return null;
        }
    }

    @Bean
    @ConditionalOnMissingBean(name = "fuction1")
    public A fuction2() {
        doSomething2();
    }

    @Bean
    public B fuction3(@Autowired(required = false) @Qualifier("function1") A a1, @Qualifier("function2") A a2) {
        if (a1 == null) {
            doSomething3(a2);
        } else {
            doSomething3(a1);
        }
    }
}

The sample code you've provided is conceptually correct.您提供的示例代码在概念上是正确的。 Of course there are compilation errors but annotations are correct.当然有编译错误但注释是正确的。

Here is a sample that compiles and works.这是一个编译和工作的示例。

@Configuration
public class ConditionalConfiguration {

    public static class A {

        private final String name;

        public A(String name) {
            this.name = name;
        }
    }

    public static class B {

        private final A a;

        public B(A a) {
            this.a = a;
        }
    }

    @Bean
    @ConditionalOnProperty(name = "a1-property")
    public A a1() {
        return new A("a1");
    }

    @Bean
    @ConditionalOnMissingBean(A.class)
    public A a2() {
        return new A("a2");
    }

    @Bean
    public B b(A a) {
        System.out.println("########## " + a.name);
        return new B(a);
    }
}

When the property a1-property is passed to the application当属性a1-property传递给应用程序时

./gradlew clean bootRun -i -Da1-property
########## a1

the bean a1 is created.创建了 bean a1

When the property is missing当财产丢失时

./gradlew clean bootRun -i
########## a2

The bean a2 is created.创建了 bean a2

Make sure to configure Gradle to pass system properties to the bootRun task by adding in the build.gradle确保配置摇篮传递系统属性设置为bootRun通过在添加任务build.gradle

bootRun {
    systemProperties System.properties
}

To be decoupled from a1 bean name, condition on bean type is used: @ConditionalOnMissingBean(A.class) instead of @ConditionalOnMissingBean(name = "a1") .为了与a1 bean 名称分离,使用 bean 类型条件: @ConditionalOnMissingBean(A.class)而不是@ConditionalOnMissingBean(name = "a1")

If you expect an exception during bean creation it is another case.如果您期望在 bean 创建期间出现异常,则是另一种情况。 When factory method annotated with @Bean throws an exception, Spring application crashes with BeanInstantiationException .当用@Bean注释的工厂方法抛出异常时,Spring 应用程序会因BeanInstantiationException崩溃。

So, exceptions should be handled in the factory method:所以,异常应该在工厂方法中处理:

@Bean
@ConditionalOnProperty(name = "a1-property")
public A a1() {
    try {
        //return new A("a1");
        throw new RuntimeException("Sample exception");
    } catch (Exception e) {
        return fallbackA();
    }
}

@Bean
@ConditionalOnMissingBean(A.class)
public A a2() {
    return fallbackA();
}

private A fallbackA() {
    return new A("a2");
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM