Depending on common libraries is not a contradiction to low coupling with microservices. You just want to make sure that the libraries you are sharing are developed for a specific concern that is independent of that of your services and that it doesn't depend on anything within your services.
Think of that library like you would for a 3rd party library. For example you mentioned that you are using spring - Just the fact that you are using spring in both microservices doesn't mean they are coupled.
That also means you have to version your libraries and leave it up to the consuming microservices team to decide when they are ready to change/upgrade versions. Here is a link for how to create different library versions in java. Also read this link with some general information about manifests.
In java you can use one of two approaches for including a versioned library.
- Include a version number in the namespace or interface/class name explicitly. This allows for the classloader to have a unique identification and being able to include multiple versions at the same time easily. (Probably the preferred way).
- Use the same name and only include a single version of the jar at a time. This means you have to replace the existing jar dependency with the new one and then adopt any potential changes. Check this great answer.
If your library is a communication client you want to consider supporting multiple versions concurrently at the server side (as to allow the separate microservices teams to adopt to newer versions in their own pace).