Skip to main content

@Lazyโ€‹

Indicates whether a bean is to be lazily initialized.

By default, Clawject creates all singleton beans eagerly when all configuration classes are instantiated. However, there are cases when we need to create a bean, not at the context initialization, but only when the consumer of the bean needs it.

warning

Be careful when @Lazy is applied to async beans with custom scope (e.g. request), it may cause that promise will be injected instead of actual value.

tip
  • Bean level annotations have precedence over class level annotations.
  • @Lazy can be applied to @Configuration class or to the bean declaration.
  • @Lazy decorator accepts optional boolean parameter that indicates is target will be lazy or not, so to make it eager, you can use @Lazy(false).

Lazy on @Configuration classโ€‹

When we put @Lazy decorator on the @Configuration class, it indicates that all the beans that are declared in configuration should be loaded lazily.

Let's have a look here:

import {Bean, ClawjectApplication, ClawjectFactory, ExposeBeans, Lazy, PostConstruct} from '@clawject/di';

class Foo {
@PostConstruct
postConstruct() {
console.log('Foo bean has been created');
}
}

class Bar {
@PostConstruct
postConstruct() {
console.log('Bar bean has been created');
}
}

@ClawjectApplication
@Lazy
class Application {
foo = Bean(Foo);
bar = Bean(Bar);

exposed = ExposeBeans<{ foo: Foo, bar: Bar }>();
}

const applicationContext = await ClawjectFactory.createApplicationContext(Application);
const foo = await applicationContext.getExposedBean('foo');
// logs: Foo bean has been created
const bar = await applicationContext.getExposedBean('bar');
// logs: Bar bean has been created

As we see, all beans are created only when we request them for the first time.

Lazy on Beansโ€‹

We can also put @Lazy decorator over the bean declaration.

import { Bean, ClawjectApplication, ClawjectFactory, ExposeBeans, Lazy, PostConstruct } from '@clawject/di';

class Foo {
@PostConstruct
postConstruct() {
console.log('Foo bean has been created');
}
}

@ClawjectApplication
class Application {
@Lazy foo = Bean(Foo);

exposed = ExposeBeans<{ foo: Foo }>();
}

const applicationContext = await ClawjectFactory.createApplicationContext(Application);
await applicationContext.getExposedBean('foo');
// logs: Foo bean has been created

Combining @Lazy on @Configuration and Beanโ€‹

You can safely combine @Lazy on @Configuration and on the bean level.

import { Bean, ClawjectApplication, ClawjectFactory, ExposeBeans, Lazy, PostConstruct } from '@clawject/di';

class Foo {
@PostConstruct
postConstruct() {
console.log('Foo bean has been created');
}
}
class Bar {
@PostConstruct
postConstruct() {
console.log('Bar bean has been created');
}
}

@ClawjectApplication
@Lazy
class Application {
@Lazy(false) foo = Bean(Foo);
bar = Bean(Bar);

exposed = ExposeBeans<{ bar: Bar }>();
}

const applicationContext = await ClawjectFactory.createApplicationContext(Application);
// logs: Foo bean has been created
await applicationContext.getExposedBean('bar');
// logs: Foo bean has been created