简体   繁体   中英

@PropertySource java.io.FileNotFoundException

I am testing Spring's @Conditional in which I load the bean depending on the value present in the .properties file. So I created a .properties file in src/main/resources/application-config.properties and I have the configuration class as:

@Configuration
@PropertySource(value = {"classpath:application-config.properties"}, ignoreResourceNotFound = false)
@ComponentScan(basePackages = {"com.app.test"})
public class ApplicationContextConfig {...}

I have 2 Condition implementations as below:

public class ConditionalBeanOne implements Condition {
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        String name= conditionContext.getEnvironment().getProperty("condition.name");
        return name.equalsIgnoreCase("condition_one");
    }
}


public class ConditionalBeanTwo implements Condition {
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        String name= conditionContext.getEnvironment().getProperty("condition.name");
        return name.equalsIgnoreCase("condition_two");
    }
}

I have respective POJO classes as:

@Component
@Conditional(value = ConditionalBeanOne.class)
public class BeanOne implements ServiceBean {}

@Component
@Conditional(value = ConditionalBeanTwo.class)
public class BeanTwo implements ServiceBean {}

When I run the application, I get following exception: Caused by: java.io.FileNotFoundException: class path resource [application-config.properties] cannot be opened because it does not exist

I am running this through main method as following:

public class ConditionalMain {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ApplicationContextConfig.class);
        .....
    }
}

I couldn't reproduce your problem so I created a complete working example based on your use case, which is also available on my GitHub . I noticed that your conditions are really the same, only the values are different, so you don't really need to duplicate the code there. Other than that, it's pretty much what you did.

I'd say that you're reinventing the wheel here. Spring Boot already has a ConditionalOnProperty which does this.

Application.java :

public class Application {
    public static void main(String[] args) {
        try (AnnotationConfigApplicationContext applicationContext =
                     new AnnotationConfigApplicationContext(ApplicationConfig.class)) {

            ApplicationConfig.GreeterService greeterService =
                    applicationContext.getBean(ApplicationConfig.GreeterService.class);

            String actual = greeterService.greeting();

            System.out.printf("Greeting: %s.\n", actual);
        }
    }
}

ApplicationConfig.java :

@Configuration
// The / doesn't matter, but I prefer being explicit
@PropertySource("classpath:/application.properties")
@ComponentScan
public class ApplicationConfig {

    @FunctionalInterface
    public static interface GreeterService {
        String greeting();
    }

    @Bean
    @ConditionalOnProperty("hello")
    public GreeterService helloService() {
        return () -> "hello";
    }

    @Bean
    @ConditionalOnProperty("hi")
    public GreeterService hiService() {
        return () -> "hi";
    }
}

ConditionalOnProperty.java :

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnPropertyCondition.class)
public @interface ConditionalOnProperty {
    String value() default "";
}

OnPropertyCondition.java :

public class OnPropertyCondition implements Condition {
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        Map<String, Object> attributes = annotatedTypeMetadata
                .getAnnotationAttributes(ConditionalOnProperty.class.getName());
        String value = (String) attributes.get("value");

        String name = conditionContext.getEnvironment().getProperty("greeting");

        return !isEmpty(name) && name.equalsIgnoreCase(value);
    }
}

application.properties :

greeting=hello

Run normally:

Output :

Greeting: hello.

Run with -Dgreeting=hi :

Output :

Greeting: hi.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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