java


How to handle cyclic dependency in spring


For example i have two beans:
class Bean1 {
private SomeService service1;
private SomeService servive2;
private Bean2 bean2;
public void doStuff() {
service1.doActualStuff();
}
public void setBean2(Bean2 bean2) {
this.bean2 = bean2;
}
public Bean2 getBean2() { return this.bean2 }
}
class Bean2 {
private Bean1 bean1;
private SomeService3 service3;
public void init() {
bean1.doStuff();
}
public void setBean1(Bean1 bean1) {
this.bean1 = bean1;
}
}
Now if i try to configure them in spring in the folllowing way:
<bean id="service1" class="SomeService">
...
</bean>
<bean id="bean1" class="Bean1">
<property name="bean2" ref="bean2"/>
<property name="service1" ref="service1"/>
...
</bean>
<bean id="bean2" class="Bean2" init-method="init">
<property name="bean1" ref="bean1"/>
...
</bean>
Init method of bean2 is executed. Bean2 has injected bean1, but bean1 itself is not fully initialized so calling bean1.doStuff() that will call service1.doActualStuff() will return into NPE. Why bean1 is not fully initialized?
Spring caches singleton beans in a not-fully-initialized state for injection into places that would otherwise be an unresolvable circular reference. In your case, the initialization order would be something like this:
Instantiate bean1 (meaning call the constructor only, not init methods)
Add bean1 to the singleton cache to handle circular dependencies
Start injecting bean1's dependencies
Instantiate bean2 to satisfy bean1's dependency
Add bean2 to the singelton cache to handle circular dependencies
Start injecting bean2's dependencies--one of these is the cached bean1 instance, which is still not fully initialized
Finish injecting bean2's dependencies
Call bean2's init method--uhoh! bean1 still isn't initted yet!
Done creating bean2
(If you actually made it this far...) Finish injecting bean1's dependencies
No init method on bean1, but this is where it would be called
Done creating bean1
Consider rethinking your design to untangle the dependencies between bean1 and bean2.
How about if you inject the first bean programatically:
class Bean2 {
private Bean1 bean1;
private SomeService3 service3;
public void init() {
bean1.doStuff();
}
public void setBean1(Bean1 bean1) {
this.bean1 = bean1;
//HERE
this.bean1.setBean2(this);
}
}
Remove the first injection from your spring xml:
<bean id="service1" class="SomeService">
...
</bean>
<bean id="bean1" class="Bean1">
<!-- NOT NEEDED ANYMORE <property name="bean2" ref="bean2"/> -->
<property name="service1" ref="service1"/>
...
</bean>
<bean id="bean2" class="Bean2" init-method="init">
<property name="bean1" ref="bean1"/>
...
</bean>

Related Links

Setting up a click listener on an item populated by a database
JAVA Callback wait methods
Background music won't stop when back button pressed (return to menu screen) Android
Spring Boot application not able to connect to backend services if left idle for few hours
Change table name in mysql with hibernate
2D terrain + collision in java
Improving images download performance in Java
Java return error? im so confused [duplicate]
How can i wait for results from background threads and then display it later?
How to store a vector in Lucene?
Drawing border around shape javafx
bluetooth sending receiving android
How to convert large XML to string in java
JTree displaying drive does not show up at all
AlertDialog not displaying in android studio
Why opening activity with slide right doesn work?

Categories

HOME
pandas
blogger
mfc
path-finding
nullpointerexception
octobercms
google-oauth
cakephp-2.5
twitter-bootstrap-4
jxls
opengl-es-2.0
portia
slick-slider
dax
row
correlation
google-cloud-spanner
apache-cayenne
vb.net-2010
ibm-odm
hapi
jsprit
serverless-framework
progressive-web-apps
highlight.js
apache-metamodel
evopdf
text-rendering
contextmenu
openedx
shared-hosting
jtextfield
sylius
hammerspoon
facet
fifo
compatibility
bluestacks
socialengine
ecto
column-family
caret
vsts-build-task
mapbox-gl
catalog
webdriver-manager
ensembles
galen
botbuilder
unixodbc
avconv
promela
pnotify
dropbox-php
idisposable
composite-key
sqlbulkcopy
visual-c++-2008
multi-level
underscore.js-templating
gstreamer-0.10
persist
associative-array
srand
qtableview
jmeter-maven-plugin
django-unittest
tmuxinator
spidermonkey
responsive-images
service-accounts
ios9.1
operation
createprocessasuser
notify
gadt
jquery-layout
valueconverter
seaside
algebraic-data-types
floating-point-precision
mysqltuner
jsctypes
dbconnection
bulkloader
jplaton
eventlistener
ocunit
netdna-api
xmlspy
appendto
iphone-web-app
datareader
cxxtest
h.323
routedevent
forums
meego
brewmp
iweb
backcolor
swing-app-framework
pascal-fc
procedural-music
msdev
rtml

Resources

Database Users
RDBMS discuss
Database Dev&Adm
javascript
java
csharp
php
android
javascript
java
csharp
php
python
android
jquery
ruby
ios
html
Mobile App
Mobile App
Mobile App