As of Spring 4.0 @Lazy can be applied on injection points, such as @Autowire or @Inject. From the docs:
In addition to its role for component initialization, this annotation may also be placed on injection points marked with Autowired or Inject: In that context, it leads to the creation of a lazy-resolution proxy for all affected dependencies, as an alternative to using ObjectFactory or Provider.
Let's start with a bit of a background. The Provider interface is part of JSR-330 and, among other usages, it allows for breaking circular dependencies and deals with lazy instantiation in general.
A quick explanatory example, a mere copy-paste from the docs:
class Car {  
   @Inject Car(Provider seatProvider) {  
     Seat driver = seatProvider.get();  
     Seat passenger = seatProvider.get();  
     ...  
   }  
}  
Start with adding a Maven dependency:
 <dependency>  
   <groupid>javax.inject</groupid>  
   <artifactid>javax.inject</artifactid>  
   <version>1</version>  
 </dependency>  
 public class Seat {..}  
import javax.inject.Inject;  
import javax.inject.Provider;  
public class Car {  
   private Seat driver;  
   private Seat passenger;  
   @Inject  
   public Car(Provider<Seat> seatProvider) {  
     driver =  seatProvider.get();  
     passenger = seatProvider.get();  
   }  
}  
@Component  
public class Car {..}  
  import org.springframework.context.annotation.Bean;  
  import org.springframework.context.annotation.Configuration;  
  import org.springframework.context.annotation.Scope;  
  import javax.inject.Provider;  
  
  @Configuration  
  public class SeatProvider implements Provider<Seat> {  
    @Override  
    @Bean  
    @Scope(value = "prototype")  
    public Seat get() {  
      return new Seat();  
    }  
}  
// Unit tests  
  ..  
   @Autowired  
   private Car car;  
   ..  
   // Instantiation should happen  
   assertNotNull(car.getDriver());  
   assertNotNull(car.getPassenger());  
   // The passenger and the driver shouldn't  
   // share the same (prototype-scoped) seat  
   assertFalse(car.getDriver().equals(car.getPassenger()));  
 }  
As of Spring 4.0, the same goal can be achieved by simply using @Lazy alongside with @Autowire. Here is how our example would change when using Spring only:
 import org.springframework.context.annotation.Scope;  
 import org.springframework.stereotype.Component;  
   
 @Component(value = "lazySeat")  
 @Scope(value = "prototype")  
 public class Seat {..}  
 import org.springframework.beans.factory.annotation.Autowired;  
 import org.springframework.context.annotation.Lazy;  
 import org.springframework.stereotype.Component;  
   
 @Component(value = "lazyCar")  
 public class Car {  
   @Autowired @Lazy  
   private Seat driver;  
   
   @Autowired @Lazy  
   private Seat passenger;  
 }  
Source Code
Previous: Part 3 - @Lazy Next: Part 5 - @Component vs @Bean
Great! Works well. Thank you for the information.
ReplyDeleteNo worries, glad I could help. Thanks.
ReplyDelete