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 ?

informatik01
  • 16,038
  • 10
  • 74
  • 104
Shadi
  • 557
  • 1
  • 6
  • 15

4 Answers4

64

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)
    })
Emerson Farrugia
  • 11,153
  • 5
  • 43
  • 51
  • 2
    What if I need to pull a bunch of individual classes from different packages? – Muhd Nov 17 '15 at 20:18
  • 3
    Add the packages to `basePackages` and the classes to the `value` attribute, making it an array using braces. – Emerson Farrugia Nov 18 '15 at 09:43
  • 3
    it works, but I was wondering if there was anything less "verbose" – Enrico Giurin Jun 07 '17 at 11:11
  • 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 path – fedd Dec 10 '17 at 11:42
  • (decided to ask a separate question https://stackoverflow.com/questions/47738564/specifying-an-individual-restcontroller-using-java-config-in-spring) – fedd Dec 10 '17 at 11:55
  • 1
    It seems like the separate question linked above was removed by mods - hopefully there wasn't anything useful in there :( – jocull Jan 28 '19 at 16:34
23

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

<bean class="my.package.MyClass" />
Bart
  • 17,070
  • 5
  • 61
  • 80
  • 6
    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... – schneida Apr 15 '16 at 12:54
  • 1
    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". – Alexander Radchenko Oct 23 '18 at 11:59
  • There is a problem @Alexander. If you have Postconstruct or Predestroy methods they will not get called. – Florian Wicher Dec 10 '19 at 16:17
  • 1
    @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... – Alexander Radchenko Dec 11 '19 at 13:40
21

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)
Robert Hunt
  • 7,914
  • 5
  • 40
  • 43
-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>
Pratik Shelar
  • 3,154
  • 7
  • 31
  • 51
  • 2
    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. – Emerson Farrugia Jan 09 '14 at 14:17