269

I have a use case where I need to call a (non-static) method in the bean only-once at the ApplicationContext load up. Is it ok, if I use MethodInvokingFactoryBean for this? Or we have a some better solution?

As a side note, I use ConfigContextLoaderListener to load the Application Context in web application. And want, that if bean 'A' is instantiated just call methodA() once.

How can this be done nicely?

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
peakit
  • 28,597
  • 27
  • 63
  • 80

6 Answers6

348

To expand on the @PostConstruct suggestion in other answers, this really is the best solution, in my opinion.

  • It keeps your code decoupled from the Spring API (@PostConstruct is in javax.*)
  • It explicitly annotates your init method as something that needs to be called to initialize the bean
  • You don't need to remember to add the init-method attribute to your spring bean definition, spring will automatically call the method (assuming you register the annotation-config option somewhere else in the context, anyway).
Koray Tugay
  • 22,894
  • 45
  • 188
  • 319
skaffman
  • 398,947
  • 96
  • 818
  • 769
  • 9
    Thanks, this works. Note if you want to use with Spring you must include "" to register the CommonAnnotationBeanPostProcessor bean (as mentioned above) – khylo Mar 14 '11 at 17:02
  • 2
    A suitable `` also works, and can be useful for reducing startup time if you have large non-Spring libraries on your classpath. – Donal Fellows May 26 '11 at 08:14
  • 5
    The JavaDoc for PostConstruct says that only one method can be annotated with it per class:http://docs.oracle.com/javaee/5/api/javax/annotation/PostConstruct.html – Andrew Swan Feb 26 '14 at 21:57
  • @PostConstruct doesn't work with a transactional manager, see: http://forum.spring.io/forum/spring-projects/data/50069-no-transaction-in-transactional-service-called-from-postconstruct/page3 – mjs Jan 15 '15 at 11:17
  • 3
    @PostConstruct also won't be of much use to you when the bean you are instantiating is not a class of your own but some third party class – John Rix Feb 24 '15 at 22:10
  • @PostConstruct is usually very helpful, but in my case I found that the Authentication instance was not available in the the SecurityContext at the time that postConstruct was called by the framework. – demaniak Oct 09 '17 at 07:50
209

You can use something like:

<beans>
    <bean id="myBean" class="..." init-method="init"/>
</beans>

This will call the "init" method when the bean is instantiated.

Betlista
  • 10,327
  • 13
  • 69
  • 110
Mercer Traieste
  • 4,670
  • 3
  • 24
  • 24
112

There are three different approaches to consider, as described in the reference

Use init-method attribute

Pros:

  • Does not require bean to implement an interface.

Cons:

  • No immediate indication in source code that this method is required after construction to ensure the bean is correctly configured.

Implement InitializingBean

Pros:

  • No need to specify init-method, or turn on component scanning / annotation processing.
  • Appropriate for beans supplied with a library, where we don't want the application using this library to concern itself with bean lifecycle.

Cons:

  • More invasive than the init-method approach.

Use JSR-250 @PostConstruct lifecyle annotation

Pros:

  • Useful when using component scanning to autodetect beans.
  • Makes it clearer that a specific method is to be used for initialisation. Intent is closer to the code.

Cons:

  • Initialisation no longer centrally specified in configuration.
  • You must remember to turn on annotation processing (which can sometimes be forgotten)
toolkit
  • 49,809
  • 17
  • 109
  • 135
  • 4
    I think it's actually a good thing to use `@PostConstruct` precisely because it is part of the class that it needs the method calling at the end of initialization processing. – Donal Fellows May 26 '11 at 08:16
  • If that class REALLY needs it and you cannot do it in constructor, than I consider it to be code smell. – user482745 Jun 22 '17 at 10:56
41

Have you tried implementing InitializingBean? It sounds like exactly what you're after.

The downside is that your bean becomes Spring-aware, but in most applications that's not so bad.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 2
    Is there a reason you would choose implementing the interface over specifying an init-method in the XML? – Mark Jul 06 '09 at 21:00
  • 4
    Thats a matter of taste. The interface is part of the Spring component model and serves that and only that purpose while for a custom named method it might not really be obvious that it has to be called to complete component lifecycle. So this serves communication mainly. Of course with the drawback of the introduced dependency to the Spring framework. A nice way in between is the usage of @PostConstruct, as it has clear semantics but does not introduce the dependency... – Oliver Drotbohm Jul 07 '09 at 17:57
  • 8
    Oliver gives me some nice excuses, but really I'd just forgotten about the init-method :) One other reason is that the type itself knows that it needs to be "finished" after all the properties have been set - it isn't fundamentally something which *should* be in the configuration. – Jon Skeet Jul 07 '09 at 18:19
8

You could deploy a custom BeanPostProcessor in your application context to do it. Or if you don't mind implementing a Spring interface in your bean, you could use the InitializingBean interface or the "init-method" directive (same link).

Rob H
  • 14,502
  • 8
  • 42
  • 45
  • Does anyone has details on how to write a BeanPostProcessor. That sounds to be exactly what I need. Cheers :) – peakit Jul 06 '09 at 18:50
  • Spring ships with many examples. Just look at the JavaDoc API for BeanPostProcessor and you'll find links to many implementing classes. Then look at the source code for them. – Rob H Jul 06 '09 at 19:17
-9

To further clear any confusion about the two approach i.e use of

  1. @PostConstruct and
  2. init-method="init"

From personal experience, I realized that using (1) only works in a servlet container, while (2) works in any environment, even in desktop applications. So, if you would be using Spring in a standalone application, you would have to use (2) to carry out that "call this method after initialization.

peterh
  • 11,875
  • 18
  • 85
  • 108
Ayorinde
  • 15
  • 1
  • 4
    Technically, `@PostConstruct` (when used in a Spring-based app) is tied to the lifespan of the owning Spring context. Such contexts can be used in all sorts of applications. – Donal Fellows May 26 '11 at 08:18
  • That was the behaviour i was expecting but didn't work for me. – Ayorinde May 26 '11 at 08:37