|
From: Colin S. <col...@ex...> - 2004-01-07 04:53:27
|
I was hoping for some more discussion on this, but it looks like nobody
bit...
In the meantime, I have clarified the existing ordering of the lifecycle
methods in the JavaDocs for InitializingBean, BeanFactoryAware, and
ApplcationContextAware.
I still think there somewhat of a (big) hole with regards to the current
initializing method handling. Currently, BeanPostProcessors are all
applied _after_ ApplicationContextAware (although this order is not
documented). This works for any BeanPostProcessors which expect to be
given fully initialized beans, as they will be given a bean initialized
fully (and knowing it) due to use of afterPropertiesSet
(InitializingBean), setBeanFactory (BeanFactoryAware), or
setApplicationContext (ApplicationContextAware). However, if somebody
needs to apply a BeanPostProcessor to set some properties of a bean as
part of the initialization, there is _no_ reliable mechanism to call an
init method on the bean afterwards; neither via an entry in the XML def,
nor via a marker interface.
What makes the most sense to _me_ is to have the following sequence apply:
- BeanFactoryAware, ApplicationContextAware, a set of 'initializing'
BeanPostProcessors, InitializingBean, and finally a another set of
'post-initializing' BeanPostProcessors.
This obviously has implications in terms of backwards compatibility
since InitializingBean applies in a different sequence. A solution which
would be completely backwards compatible (but I think less obvious),
would be to do
- InitializingBean, BeanFactoryAware, 'initializing' BeanPostProcessors,
ApplicationContextAware, 'post-initializing' BeanPostProcessors. People
could in this case use any of the three marker interfaces to initialize,
as suitable...
Any comments?
Regards,
Colin
Colin Sampaleanu wrote:
> I think any distinction between 'basic JavaBean stuff' and
> 'application context stuff' is often going to be artificial. If you
> think about some class that actually needs the context, it is probably
> going to use it in a similar fashion to any other property inside it.
>
> But the initialize method (or the specific instance
> afterPropertiesSet) is also a lifecycle method, and it is in the wrong
> order as far as _any_ BeanPostProcessors are concerned, including
> ApplicationContextAware. Right now there is no mechanism to specify
> that an init method should be called after everything has been done to
> it by the context, including post processors. You can't even rely on
> setApplicationContext() as your init method because in fact some
> post-processors may act after it.
>
> If you think about it, you should be able to take a working
> beanfactory, with working beans, and if you need something special
> from the application context (like the post-processors, or indirectly,
> via the fact that one of its dependencies needs the application
> context) just switch to using the same setup in an application
> context. You can't really do that if you can no longer rely on the
> original init methods from when you were in the bean factory.
>
> So for sure I think there is a need for the ability to call an init
> method once post-processing is done, and I can't see the justification
> for making this different than the existing beanfactory init mechanism...
>
> Regards,
> Colin
>
> Rod Johnson wrote:
>
>> Colin,
>>
>> I like the present order: not surprisingly, perhaps, as I chose it. The
>> rationale is: get the basic JavaBean stuff in order first, then do any
>> application context stuff.
>>
>> Certainly the docs should be consistent.
>>
>> Now at least I understand the confusion: setApplicationContext() is not
>> treated as a normal JavaBean property, but as a lifecycle method.
>> Perhaps
>> the "set" prefix was unwise.
>>
>> Regards,
>> Rod
>>
>> ----- Original Message ----- From: "Colin Sampaleanu"
>> <col...@ex...>
>> To: <spr...@li...>
>> Sent: Monday, January 05, 2004 8:35 PM
>> Subject: [Springframework-developer] Rationale for
>> setApplicationContext()
>> coming after afterPropertiesSet()
>>
>>
>> I've had a couple of discussions now with people where I've tried to
>> explain why setApplicationContext comes after afterPropertiesSet (and
>> after any custom initializing method you define), and frankly, I think
>> it just doesn't make sense except for the fact that it's that way
>> right now.
>>
>> Most beans should of course not be using the application context, but if
>> they need it, people are not going to understand the rationale as to why
>> that property is set after the initializing method is called, and that
>> they must instead treat setApplicationContext itself as an initializer
>> method.
>>
>> I don't know if anybody thinks it's worth changing the order, but if
>> not, this thing is going to hit new users on the head on a regular
>> basis... At a minimum, if no code is changed, we need to update the
>> JavaDoc for ApplicationContextAware to explain the order. I can do
>> that...
>>
>> Regards,
>> Colin
>>
>> jürgen höller [werk3AT] wrote:
>>
>>
>>
>>> Actually, this is intended behavior, although it may be debatable
>>> whether
>>>
>>
>> it is appropriate. setApplicationContext is not really meant to be
>> combined
>> with an init-method. The latter is for non-Spring-aware beans, while the
>> former is the strongest dependency a bean can have on Spring. You should
>> *not* design your beans to depend on that initialization order.
>>
>>
>>> As a solution, you could put your initialization code in your
>>>
>>
>> setApplicationContext implementation, or in an initApplicationContext()
>> method that gets triggered by setApplicationContext. Have a look at the
>> ApplicationObjectSupport convenience base class, it provides such a
>> method
>> out of the box. Of course, extending ApplicationObjectSupport is not an
>> option if you already have a different natural base class.
>>
>>
>>> Juergen
>>>
>>>
>>> -----Original Message-----
>>> From: Keith Donald [mailto:kd...@cs...]
>>> Sent: Thursday, October 30, 2003 4:22 PM
>>> To: spr...@li...
>>> Subject: RE: [Springframework-user] setApplicationContext not being
>>> called
>>>
>>>
>>> Juergen,
>>>
>>> Wanted to update you on this issue post M2. setApplicationContext
>>> is being
>>>
>>
>> called now on all my ApplicationContextAware beans, thanks. The only
>> issue
>> I have remaining is it seems the bean init-method method
>> ("initialize()" in
>> my case) is called by the container before setApplicationContext. My
>> initialize() method does stuff that requires the context - for
>> example, it
>> looks up messages for initializing view components. So I would
>> really need
>> setApplicationContext() called before initialize() to prevent
>> NullPointerExceptions.
>>
>>
>>> Thanks,
>>> Keith
>>>
>>> 2003-10-30 10:16:58,099 DEBUG [com.csi.cogids.console.QueryNavigator] -
>>>
>>
>> <initialize called>
>>
>>
>>> 2003-10-30 10:16:58,193 DEBUG
>>> [com.csi.cogids.console.qQueryNavigator] -
>>>
>>
>> <setApplicationContext called>
>>
>>
>>> Keith Donald
>>> Senior Software Engineer
>>> kd...@cs...
>>> 321-676-2923 x403
>>>
>>>
>>>
>>>
>>> -----Original Message-----
>>> From: spr...@li...
>>>
>>
>> [mailto:spr...@li...] On Behalf Of
>> jürgen höller [werk3AT]
>>
>>
>>> Sent: Thursday, October 23, 2003 2:14 AM
>>> To: spr...@li...
>>> Subject: Re: [Springframework-user] setApplicationContext not being
>>> called
>>>
>>>
>>> Keith,
>>>
>>> This was caused by the fact that ApplicationContextAware was being
>>>
>>
>> processed after the underlying bean factory finished its work, on
>> demand in
>> getBean calls to the application context. I've completely reworked
>> this for
>> 1.0 M2; now, the bean factory has a BeanPostProcessor hook that is also
>> internally used for processing ApplicationContextAware beans, to be
>> applied
>> when the underlying bean factory creates any kind of bean.
>>
>>
>>> So as of 1.0 M2, to be released tomorrow, this should work properly
>>> in all
>>>
>>
>> cases. If there should be any remaining issues, please report them
>> against
>> 1.0 M2. If you're eager, you can also try a CVS snapshot today.
>>
>>
>>> Juergen
>>>
>>>
>>>
>>> -----Ursprüngliche Nachricht----- Von: Keith Donald
>>> [mailto:kd...@cs...]
>>> Gesendet: Di 21.10.2003 19:50
>>> An: spr...@li...
>>> Cc:
>>> Betreff: [Springframework-user] setApplicationContext not being called
>>>
>>>
>>>
>>> Forgive me if this issue has already been addressd. It appears
>>> setApplicationContext(ApplicationContext) is not being called on my
>>> ApplicationContextAware prototype beans that are not directly
>>> instantiated
>>> by a call to beanFactory.getBean(beanName), but rather are wired
>>> "child"
>>> beans instantiated as a result of a <bean ref> references from a parent
>>> prototype.
>>>
>>> To give you an example of what I mean:
>>>
>>> // parent prototype
>>> <bean id="sessionVisualizerPage"
>>> class="com.csi.cogids.console.SessionVisualizerPage"
>>> singleton="false">
>>> <property name="queryNavigator"><ref
>>> bean="queryNavigator"/></property>
>>> </bean>
>>>
>>> // child prototype
>>> <bean id="queryNavigator"
>>> class="com.csi.cogids.console.query.QueryNavigator"
>>> singleton="false"
>>> init-method="initialize">
>>> <property name="newQueryAction"><ref
>>> bean="newQueryAction"/></property>
>>> <property name="newGroupAction"><ref
>>> bean="newGroupAction"/></property>
>>> </bean>
>>>
>>> A sessionVisualizerPage prototype gets instantiated when the page is
>>>
>>
>> loaded
>>
>>
>>> in my application. The queryNavigator prototype also gets instantiated
>>> because of the <bean ref>. setApplicationContext() IS called on
>>> sessionVisualizerPage, but not on QueryNavigator, even though both are
>>> ApplicationContextAware for message lookups.
>>>
>>> Thanks,
>>> Keith
>>>
>>> Keith Donald
>>> Senior Software Engineer
>>> kd...@cs...
>>> 321-676-2923 x403
>>>
>>
|