|
From: Andy D. <an...@ma...> - 2004-03-26 16:12:24
|
=2D----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 I hate to crosspost, but the conversion in the help forum is progressing, a= nd=20 I still want to bounce this idea off of the Spring developers. See the end= =20 of this message for a possible "solution". - Andy On Thursday 25 March 2004 09:49 am, Andy Depue wrote: > Hello, > I posted a message to the Spring "help" forum, and it has become more of > a development idea. I'd like to copy the two help forum messages here and > solicit feedback from Spring developers. You will find the two messages > below. > Thanks for your consideration. > > First message, posted 3/24/04: > > <<<<<<<<<<<< > > I have two questions regarding Spring's instantiation of beans that are n= ot > singletons. > First, let's say I have the following XML: > > ---- > <beans> > <bean id=3D"a" class=3D"A" singleton=3D"false"> > <property name=3D"b"> > <ref bean=3D"b"/> > </property> > </bean> > > <bean id=3D"b" class=3D"B" singleton=3D"false"> > <property name=3D"c"> > <ref bean=3D"c"/> > </property> > </bean> > > <bean id=3D"c" class=3D"C" singleton=3D"false"> > <property name=3D"a"> > <ref bean=3D"a"/> > </property> > </bean> > </beans> > ---- > > What will Spring do when I attempt to get "a"? Will this even work? How > many times will each class be instantiated? > The second question is similar to the first. Here is another config file: > > ---- > <beans> > <bean id=3D"a" class=3D"A" singleton=3D"false"> > <property name=3D"b"> > <ref bean=3D"b"/> > </property> > > <property name=3D"c"> > <ref bean=3D"c"/> > </property> > </bean> > > <bean id=3D"b" class=3D"B" singleton=3D"false"> > <property name=3D"c"> > <ref bean=3D"c"/> > </property> > </bean> > > <bean id=3D"c" class=3D"C" singleton=3D"false"> > </bean> > </beans> > ---- > When I attempt to get "a", how many times will "c" be instantiated? Once > for each reference, or once for the entire getBean call? > > <<<<<<<<<<<<<<<<<<<<< > > I then decided to perform my own tests based on the two examples above.=20 > Here is my response: > > <<<<<<<<<<<<<<<<<<<<< > > Well, I've tested it, and my fears are confirmed. Everytime a non-singlet= on > is referenced in the XML, it is re-instantiated. I haven't looked at > Spring's source code, but I'm guessing it is using getBean internally to > get a bean referenced in the XML. This means that the first example never > returns. It is either stuck in an infinite loop, or it is in infinite > recursion, though after a minute of running I didn't get a StackOverflow. > The second example instantiates C twice, though it does return. > What I need is the ability to have an object graph instantiated every ti= me > getBean is called, though in that instantiation, referenced objects should > only be instantiated at most one time. > Look at the second example. What we would like is the ability to have A, > B, and C instantiated every time getBean is called, but each class should > be instantiated at most once. In other words, the same C reference is > passed to both A and B, though all these objects will be reinstantiated t= he > next time getBean is called. The behavior we are looking for would be > exactly the same as if all the beans were singletons, but we used a new > XmlBeanFactory for every call of getBean. Of course, this is a possible > solution to our problem, but I'm guessing it would be terribly ineffecien= t. > Right now there are two "types" of bean instantiation: singleton, and > non-singleton. Does anyone see value in creating a third type? This new > type would indicate, "create a new instance of the object for each > getBean(...) call, but never more than one instance, so that all referenc= es > within the scope of the getBean(...) call get the same instance on > reference." > Here is one thought on a solution. First, let's say the two examples above = use=20 all Singletons. With singletons, the two examples actually work (though you= =20 won't get a new instance every getBean call), because Spring "eagerly cache= s"=20 the instances (I'm assuming). In other words, the moment Spring instantiate= s=20 an instance, it puts it in the cache even before the bean has been fully=20 initialized. It is impossible to get around circular references in=20 constructors (since the beans haven't been cached because they haven't been= =20 instantiated), but that's OK... I can live with that. In the two examples=20 above, beans are wired with properties (not constructor arguments). So,=20 Spring would instantiate A, put it in the cache, instantiate B, put it in t= he=20 cache, instantiate C, put it in the cache, then pull the cached instance of= A=20 and set the 'a' property on C, and so on. With that in mind, consider the option of creating some new kind of=20 "instantiation" type. I don't know, let's say there is a=20 singleton=3D"per-getbean" option (for lack of a better term). How would thi= s be=20 implemented? Use two levels of "cache", one that is factory wide (as it is= =20 currently implemented), and one that is "getBean" wide. Regular singletons= =20 get cached in the factory wide cache, non-singletons don't get cached at al= l,=20 and "per-getbean" singletons get cached in the "getBean" cache. Obviously,= =20 you would have to implement this getBean cache as either a cache object tha= t=20 gets passed around to all the methods that getBean calls, a thread local=20 variable, or some such thing. Whatever the case, getBean would clear its=20 local cache before returning (though it wouldn't dispose of the objects, mu= ch=20 how non-singletons work). This would solve the problem: upon every invocation of getBean, getBean's= =20 local cache would be empty, thus ensuring that each "per-getbean" singleton= =20 is instantiated per getBean call, but never more than once in the scope of= =20 that call. It would also ensure that singletons and non-singletons continue= =20 to work as they do now. This would not only provide backward compatibility,= =20 but would also solve the issue that Al brought up: what if you want some to= =20 be instantiated every reference, and others insantiated only "per getbean"?= =20 Use singleton=3D"false" for one, and the per-getbean option for the other. Thoughts?=20 =2D----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.4 (GNU/Linux) iD8DBQFAZFZfdgQy3TUmt38RAshFAJ9kj5YkdQ1kn5vNg85xq+F898NBYgCdE3qL NfYsOsQo3IgKLpngkN2aIXk=3D =3D43tK =2D----END PGP SIGNATURE----- |