16

I am using Java-based config to set up my Spring application context like this:

@Configuration
@Lazy
@ComponentScan(basePackageClasses = {MyProject.class, OtherProject.class})
public class MyAppConfig {
    ...
}

Beans defined explicitly in the config are loaded lazily, like you would expect. However, scanned classes annotated with @Named are always loaded eagerly. How can I solve this?

Any help is appreciated.


Note that for classes in the MyProject package, I can work around this by annotating them with @Lazy as well. But the other project does not have a dependency to Spring and I want to keep it like that (hence @Named and not @Component).


Note also that this does not seam to be a problem in XML-based config. There, setting default-lazy-init="true" in the <beans> tag seams to do what I want (although I haven't tested that).

rolve
  • 10,083
  • 4
  • 55
  • 75
  • 3
    So try adding small `` XML file and leave rest to Java Configuration. If there is no way to do this with `@Configuration`, don't hesitate to [raise an issue](https://jira.springsource.org/secure/Dashboard.jspa). – Tomasz Nurkiewicz Aug 31 '12 at 17:01
  • check this: http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/context/annotation/Lazy.html – Elbek Sep 27 '12 at 16:45
  • 2
    There's a bug report open on this: https://jira.spring.io/browse/SPR-10459 – Deepak Sarda Jun 30 '14 at 07:42

3 Answers3

21

As of version 4.1 RC2, this bug is fixed, and you can accomplish lazy loading on component scan with:

@ComponentScan(basePackages = ["..."], lazyInit = true)

https://jira.spring.io/browse/SPR-10459

rolve
  • 10,083
  • 4
  • 55
  • 75
Eric S.
  • 256
  • 2
  • 5
  • Hi, thanks a lot for the answer! I observed that the lazyInt = true has to work in combination with the @Lazy for the entire config class; otherwise, it won't work. That seems redundant on the "lazy" part. Is that an intended behavior? – q3769 Oct 18 '18 at 15:37
2

As you said before there is no direct way to handle that (using @Lazy in the configuration class). But you can try with this approach:

I suppose that OtherProject is a project that is not using Spring, and imagine that these classes are not annotated.

Then you should define in Myproject a configuration that looks like that:

@Configuration
// Avoid use this line if classes aren't annotated @ComponentScan("com.otherProject")
public class MyProjectConfig {

    @Bean(name = "lazyBean")
    @Lazy
    public LazyBean lazyBean(){
        System.out.println("Loading LazyBean bean");
        return new LazyBean(); // Or use a static method factory, this is only an example
    }
}

Using this, the bean "lazyBean" will be created when some instance inject it or when you explicity call it, but never at init time.

Please note that you need to define a new bean per class that you want to use, so this is not good if you have tons of classes but good to minimize the accessibility of classes of your other project (perhaps not all your classes are necessary).

I hope this helps.

sgroh
  • 354
  • 1
  • 12
  • Actually, the other project's classes *are* annotated, but with `@Named`. Therefore, I wanted to take advantage of the `@ComponentScan` and avoid having to define all beans explicitly. But thanks for your time, I'll accept your answer. – rolve Sep 27 '12 at 17:18
2

From Spring Boot 2.2, you can set a property to true (default to false) to enable the lazy initialization :

spring.main.lazy-initialization=true
davidxxx
  • 125,838
  • 23
  • 214
  • 215