We've written an in-house service discovery (SD) client based on the spring-cloud-commons SPI, meaning it provides implementations for interfaces ServiceRegistry
and DiscoveryClient
and some other Spring-provided abstractions.
Apps that use our library merely add it to their pom file, and it autowires the DiscoveryClient
with its own implementation, InHouseDiscoveryClient
<dependency>
<groupId>blah.blah<groupId>
<artifactId>inhouse-service-discovery-client<artifactId>
<dependency>
However, rather than referring to InHouseDiscoveryClient
in code, it's best practices to use the interface DiscoveryClient
as shown below
# Good
@Autowired
DiscoveryClient client;
# Bad (binds app to a particular SD implementation)
@Autowired
InHouseDiscoveryClient client;
As such, we are required to add spring-cloud-commons
to the project.
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons</artifactId>
</dependency>
This is where the issue starts. The commons library actually autowires two additional implementations of DiscoveryClient
- the SimpleDiscoveryClient
and the CompositeDiscoveryClient
.
This makes for an odd user experience for our clients. Instead of simply having InHouseDiscoveryClient
, users find themselves with these additional beans.
Is it possible to prevent spring-cloud-commons
's DiscoveryClient
implementations from autowiring? And if so, can this be done in our library rather than in the end-user's applications?
I ended up extended AutoConfigurationImportFilter
in my library to remove the autowired beans from cloud-commons. I also removed it's health indicator, but we had a very particular reason to do so - most probably would rather keep it.
my.package
public class StratusDiscoveryExclusionFilter implements AutoConfigurationImportFilter {
private static final Set<String> SHOULD_SKIP = new HashSet<>(
Arrays.asList(
// DiscoveryClient Beans
"org.springframework.cloud.client.discovery.composite.CompositeDiscoveryClientAutoConfiguration",
"org.springframework.cloud.client.discovery.simple.SimpleDiscoveryClientAutoConfiguration",
// Health indicators
"org.springframework.cloud.client.CommonsClientAutoConfiguration")
);
/**
* For each class name, provide an assocated boolean array indicated whether or not to include
*/
@Override
public boolean[] match(String[] classNames, AutoConfigurationMetadata metadata) {
boolean[] matches = new boolean[classNames.length];
for (int i = 0; i < classNames.length; i++) {
matches[i] = !SHOULD_SKIP.contains(classNames[i]);
}
return matches;
}
}
I think add a reference to this in my library's spring.factories
file
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=my.package.MyExclusionFilter