I have a project with a Spring container. Let's say this project is called my-common-library
and uses the namespace my.common
. It scans all components in this namespace, as specified in common-context.xml
which looks like following
<beans ...>
<context:component-scan base-package="my.common"/>
</beans>
Among other things this scan detects classes annotated with @MyComponent
.
Now I would like to reuse this project as fully as possible. Let's say I start a new project my-client
which uses in the namespace my.client
. The my-client
mostly consists of components annotated with @MyComponent
.
In the ideal world I would just add the dependency my-common-library
and all @MyComponent
s will be scanned and registered. The only problem is the new namespace is unknown to the original my-common-library
.
One solution that I'm aware of is to add an updated common-context.xml
to my-client
which would look like
<beans ...>
<context:component-scan base-package="my.common,my.client"/>
</beans>
That would certainly work, but seems quite fragile. Is there a more elegant solution maybe?
Attempting to implement component registration from libraries via component-scan is always fragile, in my opinion.
If you are just reusing code, I recommend explicitly importing the my-common-library
dependency. For example, using Java-based Spring configuration:
@Configuration
@ComponentScan("my.common")
public class MyCommonLibraryConfig {
}
On 'my-client`:
@Configuration
@Import(MyCommonLibraryConfig.class)
@ComponentScan("my.client")
public class MyClientConfig {
}
Since my-client
always depends on my-library
, it is best to define the dependency explicitly.
On the other hand, if what you actually want is to implement something like a plugin system, then you will need to use some package-based convention to discover dependencies since the component using the dependencies does not know what its dependencies until run-time.
In that case, I recommend defining a registration package name such as my.plugin
, then the Spring configuration for the component that depends on the plugins just need to define component scan on my.plugin
, and each plugin just need to define its @Components
or its @Configurations
beans in the same my.plugin
package.
If you want more control, you can add a filter to the component-scan so that you only register the bean with a certain annotation. For example, assuming you define a @MyPlugin
annotation:
@ComponentScan(
basePackages = {"my.plugin"},
includeFilters = @ComponentScan.Filter(
value= MyPlugin.class,
type = FilterType.ANNOTATION
)
)