> Spring is close to impossible to debug, because everything is driven by annotations, configuration settings, property files, beans defined in XML, default values, or code that runs because you added a dependency even though you never explicitly call it.
I see a comment like this every week on HN and I've been meaning to write a blogpost or two to address this.
Yes, as you mentioned there is a myriad of ways to configure a Spring(Boot) application, and I think that is one of things that make it such a powerful framework or platform to build a service on. To address a few of your points:
* beans defined in XML : we don't do that anymore since annotations got introduced. I haven't written a beans.xml file in years.
* Program logic is exactly where you expect it: in the Java code. All the property files and annotations are used for configuration to allow for different environments. This setup allows us to run the exact same binary jar or docker image built from CI to run in CI, in dev, in staging and in multiple different production environments.
* configuration settings and property files are the same thing as the configuration values go into property files, you can have multiple property files to group configuration logically by their purpose, and if needed duplicate each property file per environment to group those together. I know my database config for the staging environment is in database-staging.properties. If that is not enough you can easily override any of the values with environment variables
* Debugging : another point where Java gets huge flak here on HN is huge stack traces, well I think those are actually helpful in figuring out exactly what is running and giving you trouble in a specific environment. And because of the separation of configuration from code mentioned above it is trivial to setup a testcase with the exact same configuration that you are having trouble with and use a debugger on that testcase to inspect and debug.
* Simplicity and composability : While the framework can look complex if you don't understand the configuration system, it is actually there to facilitate composability. See my point about running the same binary in all environments. The big idea is that you put all code in the same repo and then compose and configure your application at runtime with the configuration system.