Package io.avaje.inject
BeanScope.
Overview
1. @Singleton / @Factory
Put @Singleton on beans that we want avaje-inject to wire.
We can use @Factory/@Bean to programmatically create dependencies
when they have interesting construction logic (e.g. construction depends on
system/environment properties etc - like Spring @Configuration).
@Singleton
public class CoffeeMaker { ... }
@Singleton
public class Pump { ... }
// Use @Factory to programmatically build dependencies
@Factory
public class MyFactory {
@Bean
Grinder buildGrinder(Pump pump) { // interesting construction logic ... }
}
2. Create and use BeanScope
Create BeanScope using a builder.
Obtain beans from the scope and use them.
We should ensure the BeanScope is closed in order to fire preDestroy lifecycle methods. We can do this via a shutdown hook, or try with resource block or explicitly via application code.
// create BeanScope
BeanScope scope = BeanScope.newBuilder()
.build();
// use it
CoffeeMaker coffeeMaker = scope.get(CoffeeMaker.class);
coffeeMaker.makeIt();
// close it to fire preDestroy lifecycle methods
scope.close();
Default scope
All beans annotated with @Singleton and @Factory are by default included in
the "default scope".
When we create a BeanScope and do not specify any modules then all the beans in the default scope are included. This is done via ServiceLoader and includes all 'default scope' modules that are in the classpath (other jars can have default scope modules and these are all included).
Generated code
avaje-inject will generate a $DI class for each bean that it is going to
wire - this has the code that instantiates the bean, performs field and method injection and
lifecycle support (PostConstruct and PreDestroy).
avaje-inject will generate a Module class for the default scope. The main job of the module code is to specify the ordering of how all the beans are instantiated.
We typically find the generated source code in target/generate-sources/annotations.
Custom scopes
We can create custom scopes that only contain the beans/components that we want to include in that scope. These beans/components in the custom scope are not included in the default scope.
To do this we:
1. Create the scope annotation
Create an annotation that has the Scope annotation. In the example below we create the
@StoreComponent annotation. We will put this annotation on beans that we want
included in the scope.
@Scope
public @interface StoreComponent {
}
Note that if this scope depends on external dependencies or another scope we specify that via
@InjectModule requires. In the example below our StoreComponent depends on another
scope called QueueComponent and an external dependency - SomeExternalDependency.
@Scope
@InjectModule(requires = {QueueComponent.class, SomeExternalDependency.class})
public @interface StoreComponent {
}
2. Use the annotation
Put the @StoreComponent annotation on the beans that we want included in the
custom scope.
@StoreComponent
public class StoreLoader {
...
}
3. Generated Module
avaje-inject will generate a StoreComponentModule with the appropriate
code to create/wire all the beans in the custom scope.
StoreComponentModule is typically found in target/generate-sources/annotations.
For each component we will also see a $DI class which is the generated code
that creates the component.
4. Use the custom scope
To use the custom scope we specify the StoreComponentModule when creating the
BeanScope. Only the components in our module will be create/wired into the BeanScope.
If the scope depends on another scope then we specify that using withParent().
BeanScope parentScope = ...
BeanScope scope = BeanScope.newBuilder()
.withModules(new StoreComponentModule())
.withParent(parentScope)
.build());
StoreLoader storeLoader = scope.get(StoreLoader.class);
storeLoader.load();
-
Interface Summary Interface Description BeanEntry A bean entry with priority and optional name.BeanScope Holds beans created by dependency injection.BeanScopeBuilder Build a bean scope with options for shutdown hook and supplying external dependencies.BeanScopeBuilder.ForTesting Extends the building with testing specific support for mocks and spies. -
Annotation Types Summary Annotation Type Description Bean Marks methods on a@Factorybean that create dependencies.Factory A singleton bean that has methods marked with the@Beanannotation.InjectModule Used to explicitly specify if it depends on externally provided beans or provides.PostConstruct ThePostConstructannotation is used on a method that needs to be executed after dependency injection is done to perform any initialization.PreDestroy ThePreDestroyannotation is used on a method as a callback notification to signal that the instance is in the process of being removed by the container.Primary Identify a bean as being the preferred bean to inject when multiple beans implement the intended interface.Priority ThePriorityannotation can be applied to classes to indicate in what order they should be returned via @BeanScope.listByPriority(Class).Secondary Identify a bean as being the least preferred bean to inject when multiple beans implement the intended interface.