I have two classes
Class B {
#Resource
C c;
}
Class A {
private final B b;
public A(B b) {
this.b = b;
}
}
Then class A is initialized using Spring through #Bean annotation as follows:
#Configuration
public class AppConfigHelper {
#Bean
public C getC() {
return new C();
}
#Bean
public B getB() {
return new B();
}
#Bean
public A getA() {
return new A(getB());
}
}
The problem that I end up with is C getting null in object of type B. Is there a solution to this problem?
I have to get A initialized this way only as the B is the old code which I do not want to touch at this point of time.
Related
I have a hierarchy of beans dependency of same parent class S as:
A -> B -> C
where Bean A contains bean B, bean B contains C with code structure something like this:
public class A extends S {
private S successor;
}
public class B extends S {
private S successor;
}
public class C extends S {
private S successor;
}
And when implementing I have
A a = new A();
B b = new B();
C c = new C();
a.successor = b;
b.successor = c;
What I really want to do here to set all the immediate above bean creation and dependency relationships in the Configuration instead of hardcoding in the code; something like:
#Configuration
public class MyConfig {
#Bean
public A a {
return new A();
}
#Bean
public B b {
B b = new B();
A a; // somehow get the bean A here
a.successor = b;
}
#Bean
public C c {
C c = new C();
B b; // somehow get the bean b here
b.successor = c;
}
}
Any inputs on how to go about this using Spring boot Dependency injection?
You can pass required beans as arguments to your provider methods.
#Bean
public A a() {
return new A();
}
#Bean
public B b(A a) {
B b = new B();
a.successor = b;
return b;
}
#Bean
public C c(B b) {
C c = new C();
b.successor = c;
return c;
}
However, this sets the a.successor only when B is injected somewhere. I believe this is not what you expect, and inverting the construction chain is desired:
#Bean
public A a(B b) {
A a = new A();
a.successor = b;
return a;
}
#Bean
public B b(C c) {
B b = new B();
b.successor = c;
return b;
}
#Bean
public C c() {
return new C();
}
I have following beans in my application
#Component
public class Main {
private A a;
#Inject
public Main(A a) {
this.a = a;
}
public A getA() {
return a;
}
public void setA(A a) {
this.a = a;
}
}
#Component
public class A {
private B b;
#Inject
public void setB(B b) {
this.b = b;
}
public B getB() {
return b;
}
}
#Component
public class B {
private A a;
#Inject
public void setA(A a) {
this.a = a;
}
public A getA() {
return a;
}
}
Component scan is for the package where this three classes were placed.
The above beans works in some environment and fails in other environment with circular dependency while create bean Main
Why is this circular dependency not very consistent?
The problem is that your bean A depends on bean B, and bean B depends on bean A. First of all, I would suggest rethinking your design. However, there are workarounds like using #Postconstruct, or #Lazy.
Here's a good reference, which explains what happens and different ways to solve the problem: http://www.baeldung.com/circular-dependencies-in-spring
Let's say I have Following classes:
public class A {
#Autowired B b;
public void doSomething(){
b.doSomeThingElse();
}
#Component
#Autowired C c;
public class B {
public void doSomethingElse(){
c.doIt();
}
How can I test A when you know I want to mock c.doIt() but want to call b.doSomethingElse(); with EasyMock?
Thanks in advance
#Autowired is nice but tend to make us forget about how to test. Just add a setter for b and c.
C c = mock(C.class);
c.doIt();
replay(c);
B b = new B();
b.setC(c);
A a = new A();
a.setB(b);
a.doSomething();
verify(c);
Or use constructor injection.
C c = mock(C.class);
c.doIt();
replay(c);
B b = new B(c);
A a = new A(b);
a.doSomething();
verify(c);
In this case, your classes become:
public class A {
private B b;
public A(B b) { // Spring will autowired by magic when calling the constructor
this.b = b;
}
public void doSomething() {
b.doSomeThingElse();
}
}
#Component
public class B {
private C c;
public B(C c) {
this.c = c;
}
public void doSomethingElse(){
c.doIt();
}
}
I am looking for a way to represent below code using spring dependency injection and comply to the solid principles.
A a = new A();
I b = new B(a);
I c = new C(a);
I d = new D(a);
Z z = new Z( Lists.newArrayList(b,c,d));
B, C and D are implementations on the same interface and a list of these is required for Z instantiation. Overall, there should be one new A instance per Z creation.
None of the objects can be a singleton, and I am stuck getting this translated to a spring xml configuration.
May you try to have a configuration like this one :
#Component
#Scope("prototype")
public class A {...}
#Component
#Scope("prototype")
public class B implements I {
private A a;
#Autowired
public B(A a) {
this.a = a;
}
}
#Component
#Scope("prototype")
public class C implements I {
private A a;
#Autowired
public C(A a) {
this.a = a;
}
}
#Component
#Scope("prototype")
public class D implements I {
private A a;
#Autowired
public D(A a) {
this.a = a;
}
}
public class Z {
#Autowired
private List<I> implementations;
}
Each implementations of I inject A directly in the constructor. Z inject all implementations if I.
I've got circular dependency and java config. While resolving it with xml config is very easy I can't resolve it with java config without #Autowired. Beans:
public class A {
private B b;
public B getB() {
return b;
}
public void setB(B b) {
this.b = b;
}
}
public class B {
private A a;
public A getA() {
return a;
}
public void setA(A a) {
this.a = a;
}
}
I've tried this(I've read that with #Bean annotation Spring won't invoke method every time bean is referenced, but in this case it's actually been invoked all the time):
#Configuration
public class Config {
#Bean
public A a() {
A a = new A();
a.setB(b());
return a;
}
#Bean
public B b() {
B b = new B();
b.setA(a());
return b;
}
}
And this, with #Autowired of Configuration class fields:
#Configuration
public class Config {
#Autowired
A a;
#Autowired
B b;
#Bean
public A a() {
A a = new A();
a.setB(b);
return a;
}
#Bean
public B b() {
B b = new B();
b.setA(a);
return b;
}
}
Also I've tried all above with #Lazy annotation. Doesn't help. But works perfectly if I annotate setters of A and B with #Autowired. But it's not what I want right now. What am I doing wrong and is there any way to resolve Circular dependency in java config without usage of #Autowired?
The behavior you want to get is the following
A a = new A();
B b = new B();
a.setB(b);
b.setA(a);
#Bean methods don't give you that. They run to completion to provide a bean instance.
You basically have to partially create one of the instances, then finish initializing it when you've created the other.
#Configuration
class Config {
#Bean
public A a() {
A a = new A();
return a;
}
#Bean
public B b() {
B b = new B();
A a = a();
b.setA(a);
a.setB(b);
return b;
}
}
or
#Bean
public B b(A a) {
B b = new B();
b.setA(a);
a.setB(b);
return b;
}
Another approach using #Autowired and #Component is to use this pattern:
#Component
class A {
private B b;
public B getB() {
return b;
}
public void setB(final B b) {
this.b = b;
}
}
#Component
class B {
private final A a;
#Autowired
public B(final A a) {
this.a = a;
a.setB(this);
}
public A getA() {
return a;
}
}
This eliminates the need for a separate #Configuration-class. Furthermore, the setB-method can possibly be package-protected if the classes exist in the same package to minimize scoping as much as possible.
I want to add another possible solution for your code. Instead of setting circular dependencies right in the config:
#Configuration
public class Config {
#Bean
public A a() {
A a = new A();
a.setB(b());
return a;
}
#Bean
public B b() {
B b = new B();
b.setA(a());
return b;
}
}
You could also let the spring do the work with the power of #Autowired annotation.
#Configuration
public class Config {
#Bean
public A a() {
A a = new A();
return a;
}
#Bean
public B b() {
B b = new B();
return b;
}
}
public class A {
private B b;
#Autowired
public setB(B b) { this.b = b; }
}
public class B {
private A a;
#Autowired
public setA(A a) { this.a = a; }
}
Of course it is non trivial from the "clean/readable/understandable" point of view because now your configuration is mixed in #Configuration and class itself. But as circular dependencies are quite rare, we could afford the hack.