Not exactly - in Gradle, you need to list as implementation only what you compile against. I.e. in the case of log4j you only list “log4j-api”.
Taking it further, if the library listed in implementation has dependencies of its own (wraps
and base
in your example), you don’t need to repeat them if your code does not call them directly. This way they won’t be accessible at compile time, but they will still be present in the runtime classpath. The benefits are faster compilation times and improved maintainability as you have fewer dependencies to worry about.
The “leak” I was talking about is when you decide to hide a library behind an API of your own design, ostensibly to allow transparent switching to a different backing library. Much too often I’ve seen such efforts end with an API that closely resembles the wrapped API, as in a custom tracing solution that is so much coupled to Log4j that there is no way to plug in Zipkin or Jaeger. This is a general warning against overcomplicating for sake of design - not specific to Gradle.
Let me know if it is clearer now