If I have a set of useful reusable Spring components how can I make them available as a library such that other projects can use just whatever subset of those components are useful to them?
E.g. I have 4 classes, X1, X2, X3 and X4, each annotated with @Component (or @Service, @Controller or whatever) and I want to bundle them into a library.
Then I have project A that's only interested in using X1 and X3 and another project B that's only interested in using X3 and X4.
How do projects A and B selectively enable just the components that they are interested in?
I'm using Spring Boot so I guess I could annotate each of my components with @ConditionalOnProperty, e.g. I could annotate X1 etc. like so:
@ConditionalOnProperty("x1.enabled")
@Component
public class X1 {
Then downstream projects would have to add x1.enabled = true to their application.properties file if they wanted to use X1.
Is this the way to do things or is there some other standard approach for bundling components for reuse?
I can think of other approaches, e.g.:
@ComponentScan to scan just the packages of the components they wanted to use.@Component on the component classes and mark them abstract and then leave it to any downstream project to simply subclass the components they want and add @Component to the subclass.The first of those ideas sounds like a complete hack, the second doesn't sound so bad but one has to create subclasses simply in order to enable something (but at least it's fairly explicit what you're doing).
Just to note - I'm using an all annotation based configuration with no XML.
The first option that you proposed, to me is a good option. You can put your classes in different packages and the scan the packages that you're interested in.
But you don't like the first option, so I suggest you the following.
You can take off the @component, of your classes and defined as beans in the configuration (xml files or @configuration classes). At the end each project configure the classes that it needs.
You then can inject those beans into others beans of the every project.
To clear up a little confusion upon reading this question:
You can indeed use @ComponentScan to scan for every @Component below the provided package name.
If you don't like that, you can create methods or parameters in your @Configuration that create instances of each of @Component you want to use.
If the creation of your beans is complicated, you can use @Import to import the whole @Configuration from your library.