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:

  1. public class V8Engine implements Engine {
  2. private final int cylinders = 8;
  3. private double rodLength; (1)
  4. public V8Engine(double rodLength) {
  5. this.rodLength = rodLength;
  6. }
  7. @Override
  8. public String start() {
  9. return "Starting V" + String.valueOf(getCylinders()) + " [rodLength=" + String.valueOf(getRodLength()) + "]";
  10. }
  11. @Override
  12. public final int getCylinders() {
  13. return cylinders;
  14. }
  15. public double getRodLength() {
  16. return rodLength;
  17. }
  18. public void setRodLength(double rodLength) {
  19. this.rodLength = rodLength;
  20. }
  21. }
  22. @Factory
  23. public class EngineFactory {
  24. private V8Engine engine;
  25. private double rodLength = 5.7;
  26. @PostConstruct
  27. public void initialize() {
  28. engine = new V8Engine(rodLength); (2)
  29. }
  30. @Singleton
  31. public Engine v8Engine() {
  32. return engine;(3)
  33. }
  34. public void setRodLength(double rodLength) {
  35. this.rodLength = rodLength;
  36. }
  37. }
  38. @Singleton
  39. public class EngineInitializer implements BeanInitializedEventListener<EngineFactory> { (4)
  40. @Override
  41. public EngineFactory onInitialized(BeanInitializingEvent<EngineFactory> event) {
  42. EngineFactory engineFactory = event.getBean();
  43. engineFactory.setRodLength(6.6);(5)
  44. return engineFactory;
  45. }
  46. }
  1. class V8Engine implements Engine {
  2. final int cylinders = 8
  3. double rodLength (1)
  4. @Override
  5. String start() {
  6. return "Starting V${cylinders} [rodLength=$rodLength]"
  7. }
  8. }
  9. @Factory
  10. class EngineFactory {
  11. private V8Engine engine
  12. double rodLength = 5.7
  13. @PostConstruct
  14. void initialize() {
  15. engine = new V8Engine(rodLength: rodLength) (2)
  16. }
  17. @Singleton
  18. Engine v8Engine() {
  19. return engine (3)
  20. }
  21. }
  22. @Singleton
  23. class EngineInitializer implements BeanInitializedEventListener<EngineFactory> { (4)
  24. @Override
  25. EngineFactory onInitialized(BeanInitializingEvent<EngineFactory> event) {
  26. EngineFactory engineFactory = event.bean
  27. engineFactory.rodLength = 6.6 (5)
  28. return event.bean
  29. }
  30. }
  1. class V8Engine(var rodLength: Double) : Engine { (1)
  2. override val cylinders = 8
  3. override fun start(): String {
  4. return "Starting V$cylinders [rodLength=$rodLength]"
  5. }
  6. }
  7. @Factory
  8. class EngineFactory {
  9. private var engine: V8Engine? = null
  10. private var rodLength = 5.7
  11. @PostConstruct
  12. fun initialize() {
  13. engine = V8Engine(rodLength) (2)
  14. }
  15. @Singleton
  16. fun v8Engine(): Engine? {
  17. return engine(3)
  18. }
  19. fun setRodLength(rodLength: Double) {
  20. this.rodLength = rodLength
  21. }
  22. }
  23. @Singleton
  24. class EngineInitializer : BeanInitializedEventListener<EngineFactory> { (4)
  25. override fun onInitialized(event: BeanInitializingEvent<EngineFactory>): EngineFactory {
  26. val engineFactory = event.bean
  27. engineFactory.setRodLength(6.6)(5)
  28. return event.bean as EngineFactory
  29. }
  30. }
1The V8Engine class defines a rodLength property
2The EngineFactory initializes the value of rodLength and creates the instance
3The created instance is returned as a Bean
4The BeanInitializedEventListener interface is implemented to listen for the initialization of the factory
5Within 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.