banner



When Is Maumelle's Spring Clean Up 2019

Providing an Inversion-of-Control Container is one of the core provisions of the Spring Framework. Leap orchestrates the beans in its application context and manages their lifecycle. In this tutorial, we're looking at the lifecycle of those beans and how nosotros tin hook into information technology.

Example Lawmaking

This article is accompanied by a working code example on GitHub.

What Is a Leap Bean?

Let's start with the basics. Every object that is nether the control of Spring's ApplicationContext in terms of creation, orchestration, and destruction is called a Spring Bean.

The most common manner to define a Bound bean is using the @Component annotation:

                          @Component              course              MySpringBean              {              ...              }                      

If Spring's component scanning is enabled, an object of MySpringBean will be added to the awarding context.

Another way is using Leap'due south Java config:

                          @Configuration              class              MySpringConfiguration              {              @Bean              public              MySpringBean              mySpringBean              ()              {              return              new              MySpringBean();              }              }                      

The Spring Bean Lifecycle

When we look into the lifecycle of Spring beans, nosotros can see numerous phases starting from the object instantiation upward to their destruction.

To keep it simple, we group them into creation and destruction phases: Spring Bean Lifecycle

Let's explain these phases in a footling bit more than detail.

Bean Creation Phases

  • Instantiation: This is where everything starts for a bean. Spring instantiates bean objects just similar nosotros would manually create a Java object example.
  • Populating Properties: After instantiating objects, Jump scans the beans that implement Enlightened interfaces and starts setting relevant properties.
  • Pre-Initialization: Spring'due south BeanPostProcessors go into action in this phase. The postProcessBeforeInitialization() methods do their task. Likewise, @PostConstruct annotated methods run correct after them.
  • AfterPropertiesSet: Spring executes the afterPropertiesSet() methods of the beans which implement InitializingBean.
  • Custom Initialization: Leap triggers the initialization methods that we divers in the initMethod attribute of our @Beanannotations.
  • Post-Initialization: Bound'due south BeanPostProcessors are in action for the 2d fourth dimension. This phase triggers the postProcessAfterInitialization() methods.

Bean Destruction Phases

  • Pre-Destroy: Spring triggers@PreDestroy annotated methods in this phase.
  • Destroy: Spring executes the destroy() methods of DisposableBean implementations.
  • Custom Devastation: We can define custom devastation hooks with the destroyMethod attribute in the @Edible bean annotation and Spring runs them in the last stage.

Hooking Into the Bean Lifecycle

There are numerous ways to claw into the phases of the edible bean lifecycle in a Spring application.

Allow's come across some examples for each of them.

Using Leap's Interfaces

We tin implement Leap's InitializingBean interface to run custom operations in afterPropertiesSet() phase:

                          @Component              class              MySpringBean              implements              InitializingBean              {              @Override              public              void              afterPropertiesSet              ()              {              //...                                          }              }                      

Similarly, we tin implement DisposableBean to have Bound call the destroy() method in the destroy phase:

                          @Component              class              MySpringBean              implements              DisposableBean              {              @Override              public              void              destroy              ()              {              //...                                          }              }                      

Using JSR-250 Annotations

Spring supports the @PostConstruct and @PreDestroy annotations of the JSR-250 specification.

Therefore, we can use them to hook into the pre-initialization and destroy phases:

                          @Component              course              MySpringBean              {              @PostConstruct              public              void              postConstruct              ()              {              //...                                          }              @PreDestroy              public              void              preDestroy              ()              {              //...                                          }              }                      

Using Attributes of the @Edible bean Notation

Additionally, when we define our Spring beans we tin can set the initMethod and destroyMethod attributes of the @Edible bean annotation in Coffee configuration:

                          @Configuration              form              MySpringConfiguration              {              @Bean              (initMethod              =              "onInitialize"              ,              destroyMethod              =              "onDestroy"              )              public              MySpringBean              mySpringBean              ()              {              return              new              MySpringBean();              }              }                      

Nosotros should note that if we have a public method named close() or shutdown() in our bean, so it is automatically triggered with a destruction callback by default:

                          @Component              class              MySpringBean              {              public              void              close              ()              {              //...                                          }              }                      

Even so, if we do not wish this behavior, we can disable it by setting destroyMethod="":

                          @Configuration              class              MySpringConfiguration              {              @Bean              (destroyMethod              =              ""              )              public              MySpringBean              mySpringBean              ()              {              return              new              MySpringBean();              }              }                      

XML Configuration

For legacy applications, we might have still some beans left in XML configuration. Luckily, we can nevertheless configure these attributes in our XML bean definitions.

Using BeanPostProcessor

Alternatively, we can brand apply of the BeanPostProcessor interface to be able to run whatsoever custom operation before or later a Spring edible bean initializes and even return a modified bean:

                          class              MyBeanPostProcessor              implements              BeanPostProcessor              {              @Override              public              Object              postProcessBeforeInitialization              (Object bean,              String beanName)              throws              BeansException              {              //...                                          render              edible bean;              }              @Override              public              Object              postProcessAfterInitialization              (Object bean,              String beanName)              throws              BeansException              {              //...                                          return              bean;              }              }                      

BeanPostProcessor Is Not Bean Specific

We should pay attention that Spring'due south BeanPostProcessors are executed for each bean defined in the spring context.

Using Enlightened Interfaces

Some other way of getting into the lifecycle is past using the Aware interfaces:

                          @Component              class              MySpringBean              implements              BeanNameAware,              ApplicationContextAware              {              @Override              public              void              setBeanName              (String proper name)              {              //...                                          }              @Override              public              void              setApplicationContext              (ApplicationContext applicationContext)              throws              BeansException              {              //...                                          }              }                      

At that place are boosted Enlightened interfaces which we can utilize to inject sure aspects of the Spring context into our beans.

Why Would I Need to Hook Into the Edible bean Lifecycle?

When we need to extend our software with new requirements, information technology is critical to find the best practices to keep our codebase maintainable in the long run.

In Bound Framework, hooking into the edible bean lifecycle is a good way to extend our application in most cases.

Acquiring Edible bean Properties

One of the utilise cases is acquiring the edible bean properties (like bean name) at runtime. For example, when we practice some logging:

                          @Component              class              NamedSpringBean              implements              BeanNameAware              {              Logger logger              =              LoggerFactory.              getLogger              (NamedSpringBean.              course              );              public              void              setBeanName              (Cord name)              {              logger.              info              (name              +              " created."              );              }              }                      

Dynamically Irresolute Spring Bean Instances

In some cases, nosotros need to define Spring beans programmatically. This tin can be a applied solution when we demand to re-create and change our bean instances at runtime.

Permit'southward create an IpToLocationService service which is capable of dynamically updating IpDatabaseRepository to the latest version on-need:

                          @Service              form              IpToLocationService              implements              BeanFactoryAware              {              DefaultListableBeanFactory listableBeanFactory;              IpDatabaseRepository ipDatabaseRepository;              @Override              public              void              setBeanFactory              (BeanFactory beanFactory)              throws              BeansException              {              listableBeanFactory              =              (DefaultListableBeanFactory)              beanFactory;              updateIpDatabase();              }              public              void              updateIpDatabase              (){              String updateUrl              =              "https://download.tiptop.com/ip-database-latest.mdb"              ;              AbstractBeanDefinition definition              =              BeanDefinitionBuilder              .              genericBeanDefinition              (IpDatabaseRepository.              course              )              .              addPropertyValue              (              "file"              ,              updateUrl)              .              getBeanDefinition              ();              listableBeanFactory              .              registerBeanDefinition              (              "ipDatabaseRepository"              ,              definition);              ipDatabaseRepository              =              listableBeanFactory              .              getBean              (IpDatabaseRepository.              class              );              }              }                      

We access the BeanFactory instance with the help of BeanFactoryAware interface. Thus, we dynamically create our IpDatabaseRepository bean with the latest database file and update our bean definition past registering it to the Spring context.

Also, we telephone call our updateIpDatabase() method right after nosotros acquire the BeanFactory instance in the setBeanFactory() method. Therefore, nosotros can initially create the first example of the IpDatabaseRepository bean while the Spring context boots up.

Accessing Beans From the Outside of the Jump Context

Another scenario is accessing the ApplicationContext or BeanFactory example from outside of the Spring context.

For example, we may want to inject the BeanFactory into a not-Spring grade to be able to access Spring beans or configurations inside that grade. The integration between Spring and the Quartz library is a expert example to show this use case:

                          course              AutowireCapableJobFactory              extends              SpringBeanJobFactory              implements              ApplicationContextAware              {              individual              AutowireCapableBeanFactory beanFactory;              @Override              public              void              setApplicationContext              (              last              ApplicationContext context)              {              beanFactory              =              context.              getAutowireCapableBeanFactory              ();              }              @Override              protected              Object              createJobInstance              (              final              TriggerFiredBundle package)              throws              Exception              {              final              Object job              =              super              .              createJobInstance              (bundle);              beanFactory.              autowireBean              (job);              return              job;              }              }                      

In this example, we're using the ApplicationContextAware interface to get access to the edible bean factory and use the bean manufacturing plant to autowire the dependencies in a Job bean that is initially not managed by Spring.

Also, a common Jump - Jersey integration is some other clear example of this:

                          @Configuration              class              JerseyConfig              extends              ResourceConfig              {              @Autowired              individual              ApplicationContext applicationContext;              @PostConstruct              public              void              registerResources              ()              {              applicationContext.              getBeansWithAnnotation              (Path.              class              ).              values              ()              .              forEach              (              this              ::annals);              }              }                      

By marking Jersey's ResourceConfig as a Spring @Configuration, we inject the ApplicationContext and lookup all the beans which are annotated past Bailiwick of jersey's @Path, to hands register them on application startup.

The Execution Social club

Let'southward write a Spring bean to encounter the execution lodge of each phase of the lifecycle:

                          class              MySpringBean              implements              BeanNameAware,              ApplicationContextAware,              InitializingBean,              DisposableBean              {              individual              String message;              public              void              sendMessage              (String message)              {              this              .              message              =              message;              }              public              String              getMessage              ()              {              render              this              .              message              ;              }              @Override              public              void              setBeanName              (Cord name)              {              System.              out              .              println              (              "--- setBeanName executed ---"              );              }              @Override              public              void              setApplicationContext              (ApplicationContext applicationContext)              throws              BeansException              {              System.              out              .              println              (              "--- setApplicationContext executed ---"              );              }              @PostConstruct              public              void              postConstruct              ()              {              Arrangement.              out              .              println              (              "--- @PostConstruct executed ---"              );              }              @Override              public              void              afterPropertiesSet              ()              {              System.              out              .              println              (              "--- afterPropertiesSet executed ---"              );              }              public              void              initMethod              ()              {              System.              out              .              println              (              "--- init-method executed ---"              );              }              @PreDestroy              public              void              preDestroy              ()              {              System.              out              .              println              (              "--- @PreDestroy executed ---"              );              }              @Override              public              void              destroy              ()              throws              Exception              {              System.              out              .              println              (              "--- destroy executed ---"              );              }              public              void              destroyMethod              ()              {              System.              out              .              println              (              "--- destroy-method executed ---"              );              }              }                      

Additionally, we create a BeanPostProcessor to hook into the before and after initialization phases:

                          class              MyBeanPostProcessor              implements              BeanPostProcessor              {              @Override              public              Object              postProcessBeforeInitialization              (Object edible bean,              String beanName)              throws              BeansException              {              if              (bean              instanceof              MySpringBean)              {              System.              out              .              println              (              "--- postProcessBeforeInitialization executed ---"              );              }              return              edible bean;              }              @Override              public              Object              postProcessAfterInitialization              (Object bean,              String beanName)              throws              BeansException              {              if              (bean              instanceof              MySpringBean)              {              System.              out              .              println              (              "--- postProcessAfterInitialization executed ---"              );              }              return              bean;              }              }                      

Adjacent, nosotros write a Bound configuration to define our beans:

                          @Configuration              form              MySpringConfiguration              {              @Bean              public              MyBeanPostProcessor              myBeanPostProcessor              (){              return              new              MyBeanPostProcessor();              }              @Bean              (initMethod              =              "initMethod"              ,              destroyMethod              =              "destroyMethod"              )              public              MySpringBean              mySpringBean              (){              return              new              MySpringBean();              }              }                      

Finally, nosotros write a @SpringBootTest to run our Leap context:

                          @SpringBootTest              class              BeanLifecycleApplicationTests              {              @Autowired              public              MySpringBean mySpringBean;              @Test              public              void              testMySpringBeanLifecycle              ()              {              Cord message              =              "Howdy World"              ;              mySpringBean.              sendMessage              (bulletin);              assertThat(mySpringBean.              getMessage              ()).              isEqualTo              (message);              }              }                      

As a result, our test method logs the execution order between the lifecycle phases:

            --- setBeanName executed --- --- setApplicationContext executed --- --- postProcessBeforeInitialization executed --- --- @PostConstruct executed --- --- afterPropertiesSet executed --- --- init-method executed --- --- postProcessAfterInitialization executed --- ... --- @PreDestroy executed --- --- destroy executed --- --- destroy-method executed ---                      

Conclusion

In this tutorial, we learned what the bean lifecycle phases are, why, and how we hook into lifecycle phases in Jump.

Spring has numerous phases in a bean lifecycle as well equally many ways to receive callbacks. We can claw into these phases both via annotations on our beans or from a mutual grade as we practise in BeanPostProcessor.

Although each method has its purpose, we should annotation that using Leap interfaces couples our lawmaking to the Bound Framework.

On the other mitt, @PostConstruct and @PreDestroy annotations are a part of the Java API. Therefore, we consider them a improve alternative to receiving lifecycle callbacks because they decouple our components even from Jump.

All the code examples and more than are over on Github for yous to play with.

Source: https://reflectoring.io/spring-bean-lifecycle/

Posted by: goldmanvizing.blogspot.com

Related Posts

0 Response to "When Is Maumelle's Spring Clean Up 2019"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel