Reading values from a property file is far superior to hard coding them in your class files. If you hard code then you need to recompile if you want to change any of them.
To answer your criticisms:
1.
System properties are iterable, PropertySource is not
Most PropertySources extend EnumerablePropertySource. Though I'm unsure of a use case where you would want to iterate over your properties
2.
PropertySource does not allow fallback properties - and creating a custom PropertySource at least equals the code of doing the same with system properties.
Rather than hide fall backs in a a custom property source you can just use the standard spring property getters. e.g.
env.getProperty("someProp", "someFallback")
or even
env.getProperty("someProp", env.getProperty("someFallback", "lastResort"))
3.
Environment and @Autowire increase Spring coupling
It's the auto-wiring that gives spring coupling, and you don't need to use it if you don't want to. e.g.
public class Foo {
private final String foo;
public Foo(String foo) {
this.foo = foo;
}
public void bar() {
// doo something with foo
}
}
and
@Configuration
@PropertySource("classpath:foo.properties")
public class Config {
@Autowired
public Environment env;
@Bean
public Foo foo() {
return new Foo(env.getProperty("foo"));
}
}