Using @ComponentScan or <context:component-scan /> with only one class
Asked Answered
N

4

35

I'm maintaining a project with two set of main packages, the project is using Spring and Spring MVC, one of these packages contains several controllers and is scanned using XML configuration (<context:component-scan />).

The problem is that there is a single class in the other package (not scanned), and I need this class to be scanned, but only this class and nothing else in the package. I can't change its package now since it would be too risky now.

So is there a way to do this using annotations or XML ?

Nuncia answered 9/1, 2014 at 13:52 Comment(4)
add the bottommost package to your context:componnent-scanSpermatocyte
the problem is that bottommost package includes other classesNuncia
If it is a single class why component-scan it. Why not simply add it as a bean to the context...Pavel
Try @Import(my.package.MyClass.class)Lubricity
A
23

Simply add is as a bean to your context e.g.

<bean class="my.package.MyClass" />
Amorist answered 9/1, 2014 at 14:10 Comment(4)
Is there a way to do just that in plain Java? I know about @Bean but then I always have to return an instance of the bean and not just the class and let spring instatiate it...Otocyst
By default spring uses no args constructor to instantiate bean. So I don't see any problems to instantiate bean in java config using "@Bean public MyClass myClass() {return new MyClass();}". And even if you call myClass() method several times you will get the same instance, unless you change bean scope from default "singleton".Johnstone
There is a problem @Alexander. If you have Postconstruct or Predestroy methods they will not get called.Scut
@FlorianWicher, AFAIK when we annotate some method with @Bean in the configuration class, Spring takes responsibility for managing bean's lifecycle. Even if you directly call that method, you actually call proxy's method (proxy wrapping Configuration class). Thus Spring is able to perform init and destroy callbacks for every call if Bean's scope is Prototype. The only exception is when you call myClass() method within Configuration class. But that's not the topic starter case, I think...Johnstone
M
65

What @Bart said for XML.

If you need to pull in that one class using annotations, add the following to one of your @Configuration classes

@ComponentScan(
    basePackageClasses = YourClass.class, 
    useDefaultFilters = false,
    includeFilters = {
        @ComponentScan.Filter(type = ASSIGNABLE_TYPE, value = YourClass.class)
    })
Medorra answered 9/1, 2014 at 14:24 Comment(6)
What if I need to pull a bunch of individual classes from different packages?Martinet
Add the packages to basePackages and the classes to the value attribute, making it an array using braces.Medorra
it works, but I was wondering if there was anything less "verbose"Leung
I, for example, am trying to use AnnotationConfigWebApplicationContext.register method, specifying an individual @RestController class, but it doesn't seem to work :( the rest controller isn't responding on the specified pathSpendthrift
(decided to ask a separate question #47739064)Spendthrift
It seems like the separate question linked above was removed by mods - hopefully there wasn't anything useful in there :(Malayopolynesian
A
23

Simply add is as a bean to your context e.g.

<bean class="my.package.MyClass" />
Amorist answered 9/1, 2014 at 14:10 Comment(4)
Is there a way to do just that in plain Java? I know about @Bean but then I always have to return an instance of the bean and not just the class and let spring instatiate it...Otocyst
By default spring uses no args constructor to instantiate bean. So I don't see any problems to instantiate bean in java config using "@Bean public MyClass myClass() {return new MyClass();}". And even if you call myClass() method several times you will get the same instance, unless you change bean scope from default "singleton".Johnstone
There is a problem @Alexander. If you have Postconstruct or Predestroy methods they will not get called.Scut
@FlorianWicher, AFAIK when we annotate some method with @Bean in the configuration class, Spring takes responsibility for managing bean's lifecycle. Even if you directly call that method, you actually call proxy's method (proxy wrapping Configuration class). Thus Spring is able to perform init and destroy callbacks for every call if Bean's scope is Prototype. The only exception is when you call myClass() method within Configuration class. But that's not the topic starter case, I think...Johnstone
S
23

In addition to the method described by Emerson Farrugia there is a less verbose solution which has been supported since Spring Framework 4.2 as mentioned in the documentation here.

As of Spring Framework 4.2, @Import also supports references regular component classes, analogous to the AnnotationConfigApplicationContext.register method. This is particularly useful if you want to avoid component scanning, by using a few configuration classes as entry points to explicitly define all your components.

So your example would simply become:

@Import(YourClass.class)
Segment answered 30/5, 2019 at 8:8 Comment(1)
Very convenient to unit test a single component with Junit. Thanks Robert !Garfieldgarfinkel
R
-3

You need to use filters to filter out other classes and just include your class which you want to be scanned

<context:component-scan base-package="com.abc" >

    <context:include-filter type="regex" 
                   expression="com.abc.customer.dao.*DAO.*" /> 

</context:component-scan>
Reconcile answered 9/1, 2014 at 14:5 Comment(1)
Why include multiple classes when he needs only one? It also won't work since use-default-filters is still true unless explicitly disabled, which you haven't done.Medorra

© 2022 - 2024 — McMap. All rights reserved.