44

According to official doc:

Annotation Type Configuration

Indicates that a class declares one or more @Bean methods and may be processed by the Spring container to generate bean definitions...

@Configuration classes may be composed using the @Import annotation, not unlike the way that works in Spring XML. Because @Configuration objects are managed as Spring beans within the container..

But i can also use @Configuration annotation without @Import. I have tested the code listed below and it works as expected. So what is the purpose to use @Import?

DispatcherServletInitializer

public class ApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[] { WebConfig.class };
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return null;
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }
    
 }

WebMvcConfigurerAdapter

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = { "package.name" })
// @Import(OptionalConfig.class) 
public class WebConfig extends WebMvcConfigurerAdapter {
    // ...
}

OptionalConfig

@Configuration
public class OptionalConfig {
    
    @Bean(name = "myClass")
    public MyClass myClass() {
        return new MyClass();
    }
}

Service

@Service
public class MyServiceImpl implements MyService {
    
    @Autowired
    private MyClass myClass;    // yes, it works

    // ...
}
Community
  • 1
  • 1
enzo
  • 786
  • 1
  • 8
  • 18

6 Answers6

31

If component scanning is enabled, you can split bean definitions in multi @Configuration classes without using @Import. And you don't need to provide all of them to the application context constructor.

I think the main purpose for @Import is to provide you a way to simplify multiple configurations registration if you'd like to avoid component scanning (as of Spring Framework 4.2, per reference manual).

There's a note in Spring Reference Documentation about @Import usage:

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

Ilya Serbis
  • 21,149
  • 6
  • 87
  • 74
yixiang
  • 890
  • 8
  • 12
23

Thus far, we've seen how to break up bean definitions into multiple @Configuration classes and how to reference those beans across @Configuration boundaries. These scenarios have required providing all @Configuration classes to the constructor of a JavaConfigApplicationContext, and this is not always ideal. Often it is preferable to use an aggregation approach, where one @Configuration class logically imports the bean definitions defined by another.

The @Import annotation provides just this kind of support, and it is the direct equivalent of the <import/> element found in Spring beans XML files.

http://docs.spring.io/spring-javaconfig/docs/1.0.0.M4/reference/html/ch04s03.html

Community
  • 1
  • 1
Marcel
  • 1,509
  • 1
  • 17
  • 39
  • 1
    yixiang's answer should be the one accepted. I'm sure the author is aware of the documentation, looking at the complexity they formulate the question.. – Simon Martineau Jul 22 '21 at 17:53
21

I found a use of using the @Import annotation. I don't think it's the use case. If you are developing a set of libraries using Spring, probably you don't have a SpringBootApplication. So, you have not enabled any auto-scan to resolve beans.

If a bean declared in a configuration file in the library library-a is referred through dependency injection in library-b you need to use @Import to tell Spring how to resolve the bean.

As we said, in library-a you have this configuration file.

@Configuration
public class ConfigurationA {
    @Bean
    public BeanA beanA() {
       return new BeanA();
    }
}

In library-b you must have this configuration file if you want to use BeanA

@Configuration
@Import(ConfigurationA.class)
public class ConfigurationB {
    @Bean
    public BeanB beanB(BeanA beanA) {
       return new BeanB(beanA);
    }
}

Hope it helps.

riccardo.cardin
  • 7,971
  • 5
  • 57
  • 106
17

With component scanning enabled it's difficult to immediately see where @Import adds value if your view of the world is limited to your own application and its packages. Where it can help is if you are importing bean libraries with their own package structure that you don't want to component scan.

You can place such libraries on your classpath and use @Import to cherry-pick @Configuration classes from within them. That's why it's often referred to as composition because you are composing your @Configuration class from multiple sources.

Andy Brown
  • 11,766
  • 2
  • 42
  • 61
12

A typical use case of @Import is when teams develop REST services and realize they need some common configuration.

Every service will have its own namespace i.e. org.mybusiness.specific and will have its @SpringBootApplication (and therefore component scan root) start at this package.

On the other hand, the common library will have its namspace set to org.mybusiness.common and will therefore be out of reach for component scanning.

Thus the need to reference the common configuration class using @Import(CommonConfig.class)

PA Lemire
  • 441
  • 5
  • 5
2

@Import works great when for some reasons you need to register not all but some of the components from a package. In such case @ComponentScan would be too complicated.

See details in the Spring boot component scan include a single class question.

Ilya Serbis
  • 21,149
  • 6
  • 87
  • 74