3.13 Bean Events
You can hook into the creation of beans using one of the following interfaces:
BeanInitializedEventListener - allows modifying or replacing of a bean after the properties have been set but prior to
@PostConstruct
event hooks.BeanCreatedEventListener - allows modifying or replacing of a bean after the bean is fully initialized and all
@PostConstruct
hooks called.
The BeanInitializedEventListener
interface is commonly used in combination with Factory beans. Consider the following example:
public class V8Engine implements Engine {
private final int cylinders = 8;
private double rodLength; (1)
public V8Engine(double rodLength) {
this.rodLength = rodLength;
}
public String start() {
return "Starting V" + String.valueOf(getCylinders()) + " [rodLength=" + String.valueOf(getRodLength()) + "]";
}
public final int getCylinders() {
return cylinders;
}
public double getRodLength() {
return rodLength;
}
public void setRodLength(double rodLength) {
this.rodLength = rodLength;
}
}
@Factory
public class EngineFactory {
private V8Engine engine;
private double rodLength = 5.7;
@PostConstruct
public void initialize() {
engine = new V8Engine(rodLength); (2)
}
@Singleton
public Engine v8Engine() {
return engine;(3)
}
public void setRodLength(double rodLength) {
this.rodLength = rodLength;
}
}
@Singleton
public class EngineInitializer implements BeanInitializedEventListener<EngineFactory> { (4)
@Override
public EngineFactory onInitialized(BeanInitializingEvent<EngineFactory> event) {
EngineFactory engineFactory = event.getBean();
engineFactory.setRodLength(6.6);(5)
return engineFactory;
}
}
class V8Engine implements Engine {
final int cylinders = 8
double rodLength (1)
String start() {
return "Starting V${cylinders} [rodLength=$rodLength]"
}
}
@Factory
class EngineFactory {
private V8Engine engine
double rodLength = 5.7
@PostConstruct
void initialize() {
engine = new V8Engine(rodLength: rodLength) (2)
}
@Singleton
Engine v8Engine() {
return engine (3)
}
}
@Singleton
class EngineInitializer implements BeanInitializedEventListener<EngineFactory> { (4)
@Override
EngineFactory onInitialized(BeanInitializingEvent<EngineFactory> event) {
EngineFactory engineFactory = event.bean
engineFactory.rodLength = 6.6 (5)
return event.bean
}
}
class V8Engine(var rodLength: Double) : Engine { (1)
override val cylinders = 8
override fun start(): String {
return "Starting V$cylinders [rodLength=$rodLength]"
}
}
@Factory
class EngineFactory {
private var engine: V8Engine? = null
private var rodLength = 5.7
@PostConstruct
fun initialize() {
engine = V8Engine(rodLength) (2)
}
@Singleton
fun v8Engine(): Engine? {
return engine(3)
}
fun setRodLength(rodLength: Double) {
this.rodLength = rodLength
}
}
@Singleton
class EngineInitializer : BeanInitializedEventListener<EngineFactory> { (4)
override fun onInitialized(event: BeanInitializingEvent<EngineFactory>): EngineFactory {
val engineFactory = event.bean
engineFactory.setRodLength(6.6)(5)
return event.bean as EngineFactory
}
}
1 | The V8Engine class defines a rodLength property |
2 | The EngineFactory initializes the value of rodLength and creates the instance |
3 | The created instance is returned as a Bean |
4 | The BeanInitializedEventListener interface is implemented to listen for the initialization of the factory |
5 | Within the onInitialized method the rodLength is overridden prior to the engine being created by the factory bean. |
The BeanCreatedEventListener interface is more typically used to decorate or enhance a fully initialized bean by creating a proxy for example.
Bean event listeners are initialized before type converters. If your event listener relies on type conversion either by relying on a configuration properties bean or by any other mechanism, you may see errors related to type conversion. |