|
From: Colin S. <col...@ex...> - 2004-12-23 04:47:37
|
Juergen, I have done some digging into this. There are in fact two levels to this issue. What I am referring to is the fact that from 1.1.1 to 1.1.2, when getBeansOfType (as used for autowiring) is called, 1.1.2+ ends up creating all factory beans so that it can call getObjectType() on them to see if the returned type is a match. 1.1.1 and earlier did not do this. Where I saw people get surprised by this is for abstract parent classes that were not marked abstract, but rather just lazy. The parent factory bean (like the TransactionProxyFactory) would get created, and it would except. Now in the case of the abstract parent the solution is just to mark it abstract, no big deal. Now I think this also triggered this circular dependency problem mentioned below. In 1.1.1 the factory beans would not get created for the getBeansOfType(), while now they do, and in Patrick's case he got the circular dependency error as Spring though two beans were depending on each other. Now I don't necessarilly know enough about his config to know if there is a real bug here that could be fixed in Spring, or there is now a real circular dependency now that the factory bean is actually being created. Sounds like the latter. Aside from the circular dependency issue, there is the basic question of whether getBeansOfType() as used for autowiring should even consider factory beans (controlled by the 'includeFactoryBeans flag) as it does now, or should not, as it worked for 1.1.1-. I sort of think the current behaviour makes sense, otherwise you will miss autowiring anything produced by FactoryBeans that have not already been instantiated. Additionally, most singletons will be pre-instantiated anyway. On the other hand, for a singleton marked lazy-init, that was probably for a reason. And the factory bean return type may not match the type, or return null, in which case it will be ignored anyway. This is sort of a chicken and egg thing, you don't want to create it if you don't need it, but you don't know if you need it until you create it... One possible solution I can see for this case is to add an optional "type" attribute which may be set on a bean def (and is only relevant for factory beans). If this exists, it would be used in lieu of a getObjectType() call on the factory bean itself. Colin jürgen höller [werk3AT] wrote: >I agree that over-eager checks should be avoided, as long as the overall semantics are not affected. Unfortunately, our test suite does not cover such cases that fail for you yet. This is the reason why it wasn't noticed that the checks became over-eager in some respects. > >Colin, could you please create unit tests for such a scenario and commit them in commented-out state (as they will currently fail, of course)? I'll try to refine the internals of the autowiring mechanism to make those test cases pass for 1.1.4 then. > >Juergen > > >________________________________ > >Von: spr...@li... im Auftrag von Patrick Burleson >Gesendet: Mi 22.12.2004 15:41 >An: spr...@li... >Betreff: Re: [Springframework-developer] Re: FactoryBeanCircularReferenceException with 1.1.3 > > > >Colin, > >Thanks for the info. It is definitely a bit of a shame for the code to >be so eager since I think a common case of Spring usage is to wrap a >service with the TransactionProxyFactory and if any service depends on >another, then autowire is probably out of the question. > >The really odd thing that added to the confusion was the fact that >Spring reported a CircularDependency when there really wasn't one. We >had service A that depended on service B (which was set to autowire), >but the circular dependency was thrown for Service C, which does >depend on A, but has nothing to do with B. Very confusing. > >With our app, we have decided that autowire shouldn't be used because >we want people who use our code to able to override our definitions >with their own. So autowiring would cause some problems. > >Overall, it would be nice to be able to specify behavior to either >revert back to the less eager method or to possibly recheck Factory >dependencies after each bean has been instantiated to see if an >autowire dpenedency has become available. (Although I guess this could >be a costly operation with lots of Factory beans). > >It would certainly seem that once you have any Factory beans, then >autowiring will probably fail for you if you have any sort of >interdepencies between the Factory targets. This is probably not the >best. > >Patrick > >On Tue, 21 Dec 2004 17:53:57 -0500, Colin Sampaleanu <col...@ex...> wrote: > > >>I've run into this while investigating some forum questions. For 1.1.2, >>Spring became much more aggressive about instantiating FactoryBeans in >>order to figure out what to autowire. Whereas the before it would not >>instantiate FactoryBeans for which a type is not known >>(getObjectType=null), it now seems to instantiate all such FactoryBeans. >> >>I'm not sure Juergen actually intended this change, or it's happening >>because he fixed some other bugs related to getBeansOfType, which I know >>happened. >> >>This is arguably not a great change. One thing it means is that every >>factory bean (which doesn't declare the return type at least) even if >>marked lazy-init, will be instantiated as soon as another bean does an >>autowire. This is what cause people who were using a parent >>TransactionProxyFactoryBean template marked only lazy=true (but not >>abstract) to all of a sudden have this parent bean start being >>instantiated when they switched from 1.1.1 to 1.1.2... >> >>I would personally vote to go back to the old behaviour... While this >>means that autowiring will not work for lazy-loaded singleton factory >>beans (that have not be instantiated yet), Spring always worked that way >>anyway, and it can be documented. >> >>Colin >> >> >>Patrick Burleson wrote: >> >> >> >>>A little more information on this: >>> >>>This has something to do with auto-wiring. The bean before the bean >>>that supposedly causes the circular reference was defined to have >>>auto-wire by type. Once I removed this definition, the circular >>>dependency went away. Is it a function of auto-wire to try and figure >>>out the type of every other bean to find dependencies? >>> >>>If so, that would probably explain it. As the target bean of a >>>transaction proxy is dependent on the bean that was defined as >>>auto-wire. But another transaction proxy target we have is dependent >>>on the other transaction proxy bean. I know that's really confusing, >>>but I think it's a common case when one service depends on another. I >>>guess that's one of the inherent dangers of auto-wiring. I just wonder >>>why it didn't fail in 1.1.1? >>> >>>Thanks, >>>Patrick >>> >>> >>>On Tue, 21 Dec 2004 11:30:18 -0500, Patrick Burleson >>><pbu...@gm...> wrote: >>> >>> >>> >>> >>>>I upgraded our app to use Spring 1.1.3 yesterday and started getting a >>>>FactoryBeanCircularReferenceException during startup. This error does >>>>not occur with Spring 1.1.1, haven't tried 1.1.2 just yet. >>>> >>>>As far as I can tell, I don't see any circular dependencies in our >>>>config. It's almost as if the factory forgot to go back and mark one >>>>of our FactoryBeans as being complete before moving on to the next >>>>Factory bean. I know that sounds impossible, and it probably is, but I >>>>at least wanted to get this out there. >>>> >>>>I'm going to try and figure out exactly why it thinks there's a >>>>circular dependency, but it might take some time. >>>> >>>>Thanks, >>>>Patrick >>>> >>>> |