Sigewine allows you to easily inject beans into your classes using annotations. In simple terms, you can define a class instance as a "bean" and then inject it into other classes that require it. This automates the process of managing class instances and passing them around, making your code cleaner and more maintainable.
In the end, Sigewine: a) creates instances of your classes, b) injects them into other classes that require them using constructors.
Features
Automatic bean injection
Automatic bean scanning
Custom bean names
Typed array list for bean injection
Extensions (Constellations) for additional functionality
Usage
Specify beans using @RomaritimeBean annotation.
Inject beans using @RomaritimeBean annotation in constructor.
Simple example
// Define a bean with @RomaritimeBean annotation
@RomaritimeBean
public class Config {
private int someValue = 10;
}
// Define a class that uses the bean
@RomaritimeBean
public class SomeService {
private final Config config;
// Sigewine automatically injects the Config bean
public SomeService(Config config) {
this.config = config;
}
public void doSomething() {
System.out.println("Config value: " + config.getSomeValue());
}
}
// Create instance of SomeService
public static void main(String[] args) {
// Create instance of Sigewine
Sigewine sigewine = new Sigewine(new SigewineOptions());
// Scan for beans in current package
sigewine.treatment("your.package.name"); // or specify a class
// Getting the beans
SomeService service = sigewine.syringe(SomeService.class);
service.doSomething(); // Outputs: Config value: 10
}
The Sigewine#treatment() method scans the specified package for classes and methods annotated with @RomaritimeBean and registers them as beans.
Method injection
You may create beans using methods annotated with @RomaritimeBean. This allows you to creat beans from classes, which cannot be annotated with @RomaritimeBean directly.
public class SomeTreatment {
@RomaritimeBean
public ExternalClass externalClass() {
return new ExternalClass();
}
}
This will allow you to inject instance of ExternalClass as it was annotated with @RomaritimeBean. Method classes may require other beans as constructor parameters and Sigewine will automatically inject them.
Custom named beans
Sometimes you may want to specify a custom name for your bean. You can do this by using the name attribute of the @RomaritimeBean annotation. This is useful when you have multiple beans of the same type and you want to differentiate them. When using them, you must specify the name in the constructor parameter.
public class Configs {
@RomaritimeBean(name = "customProductionConfig")
public Config productionConfig() {
return new Config();
}
@RomaritimeBean(name = "customDevelopmentConfig")
public Config developmentConfig() {
return new Config();
}
}
public class ProductionService {
private final Config config;
// Injects the bean with custom name
public ProductionService(
@RomaritimeBean(name = "customProductionConfig") Config config
) {
this.config = productionConfig;
}
}
public class DevelopmentService {
private final Config config;
// Injects the bean with custom name
public DevelopmentService(
@RomaritimeBean(name = "customDevelopmentConfig") Config config
) {
this.config = config;
}
}
Abstract bean definitions
Sometimes you have a bean that implements an interface or an abstract class. Sigewine respects this and allows you to specify bean by the abstract class. The injected class will be the implementation of the abstract class or interface.
// An abstract class that defines a service
public abstract class BaseService {
public abstract void performAction();
}
// An implementation of the abstract class
@RomaritimeBean
public class ConcreteService extends BaseService {
@Override
public void performAction() {
System.out.println("Action performed by ConcreteService");
}
}
@RomaritimeBean
public class ServiceConsumer {
private final BaseService service;
// Sigewine automatically injects the ConcreteService bean
public ServiceConsumer(BaseService service) {
this.service = service;
}
public void useService() {
service.performAction(); // Outputs: Action performed by ConcreteService
}
}
Collection of beans
If you have multiple beans that extend a common base class or implement a common interface, you can inject them as a collection.
// Define a base entity interface
public interface BaseEntity {
// Common properties and methods for all entities
}
// Define player entity
@RomaritimeBean
public class PlayerEntity implements BaseEntity {
// Player specific properties and methods
}
// Define NPC entity
@RomaritimeBean
public class NpcEntity implements BaseEntity {
// NPC specific properties and methods
}
// Define a service that uses all BaseEntity beans
@RomaritimeBean
@RequiredArgsConstructor
public class GameWorld {
// Injects all beans that extend BaseEntity
private final List<BaseEntity> entities = new TypedArrayList<>(BaseEntity.class);
}
Self-injected beans
You may self-inject beans into themselves. This is useful for beans that need to call their own methods and for the AOP-like method interception.
@RomaritimeBean
@RequiredArgsConstructor
public class SomeService {
@RomaritimeBean
private SomeService self; // Self-injected bean
}
Lombok
I recommend using Lombok's @RequiredArgsConstructor to avoid boilerplate code. Keep in mind that you won't be able to specify per-parameter bean names with it.
Extensions -- Constellations
Sigewine supports extensions that allows you to process beans when they are registered. They are named Constellations.
One of the existing implementation is AOP extension, that allows you to wrap methods of beans with additional functionality. Please, check the AOP subpage for more information.
Defining constellation
public class CustomConstellation extends SigewineConstellation {
public CustomConstellation() {
super(10); // Priority. Smaller values are processed first.
}
@Override
public void processBeans(Sigewine sigewine) {
// This method is called when beans are registered.
// You can process them here, for example, by adding additional properties or modifying them.
// Example: Print all beans
sigewine.getSingletonBeans().forEach((definition, bean) -> {
System.out.println("Processing bean %s of type %s".formatted(
definition.getName(),
bean.getClass().getName()
));
});
}
}
// Registering the constellation
public static void main(String[] args) {
// Create instance of Sigewine
Sigewine sigewine = new Sigewine(new SigewineOptions());
// Add custom constellation
sigewine.addConstellation(new CustomConstellation());
// Scan for beans in current package
sigewine.treatment("your.package.name");
}