There are two classes class A and class B. class B is spring bean and autowired in class A. Class A is not spring bean.
public class A {
int a,c;
public A(int a, int c ){
this.a = a;
this.c = c;
}
#Autowired
B b
// some logic
}
class C {
// Can object will be created
A obj = new A(10,12);
}
if code will compile what will happen I mean object of B will be created.
Object of class B will be created at application start-up, but will not be injected into instance of A, since it's not a spring managed bean.
Related
I have to work with existing library of my company which has bunch of #Bean packaged in #Configuration in Spring project but would be added as dependency for my project. The situation would be similar to
#Configuration
Class A{
#Bean
B b(){
return new B()
}
}
#Configuration
Class C{
#Bean
D d(){
D d = new D();
//TODO: How do I use instance of B here
d.someConfiguration(B b);
return d;
}
}
Should I initialized A using new operator in C and call method b or should I #Autowire B in C directly.
There are multiple ways you can do this
By field Autowiring
#Configuration
Class C{
#Autowire
private B b;
#Bean
D d(){
D d = new D();
//TODO: How do I use instance of B here
d.someConfiguration(B b);
return d;
}
}
By constructor Autowiring (Personally i prefer using constructor Autowiring which will be help during test cases)
#Configuration
Class C{
private B b;
#Autowire
public C(B b){
this.b=b;
}
#Bean
D d(){
D d = new D();
//TODO: How do I use instance of B here
d.someConfiguration(B b);
return d;
}
}
Or you can just add it as method arguments spring will resolve it
#Configuration
Class C{
#Bean
D d(B b){
D d = new D();
//TODO: How do I use instance of B here
d.someConfiguration(B b);
return d;
}
}
When you include the library sa a dependency, then when springboot initializes it scans the #Configuration files in those libraries as well. So the beans declared in those are already available in spring context.
So what you can do is just include it as a method parameter
#Configuration
Class C{
#Bean
D d(B b){
D d = new D();
d.someConfiguration(b);
return d;
}
}
As soon as spring see that you want a bean if type B it will search and give u an instance.
I would say its evil to use new in spring :)
I have a class file as below
import com.google.inject.Inject;
import lombok.Builder;
#Builder
public class A {
private final B objB;
private final C objC;
#Inject
public A(B b, C c) {
this.objB = b;
this.objC = c;
}
}
Now if I have to use this object in another class, will the .builder() method takes care of the dependencies being injected.
public class Main {
public void doSomething() {
A a = A.builder().build();
a.getObjB(); // Will it be null ?
a.getObjC(); // Will it be null ?
Injection always only works when you let guice deal with instance creation.
So when you use
#Inject
private A a;
guice will find that it needs a B and a C to create A and inject it.
But when you instantiate A yourself, it does not matter if via new or via builder() guice does not know about the instance creation, thus in your example, B and C will be null.
I am a newbie in Spring Framework and I came across the below POJO beans:
#Component
Class A{
#Autowired
B b;
}
#Component
Class B{
// primitive variables
}
My doubt is what will be the order of initialisation and injection of beans?
Will it be:
Instance of A is created(Constructor is called of A)
Instance of B is created(Constructor is called of B)
B is injected into A
OR
Instance of B is created(Constructor is called of B)
Instance of A is created(Constructor is called of A)
B is injected into A
I have object A
#Component("a")
Class A{
public SomeObject getC(){
return anObject;
}
}
that I want to use in the construction of another object B like so
#Service("b")
Class B{
#Autowired
#Qualifier("a")
A a;
SomeObject c;
public B(){
c = a.getC();
}
Where a is a connector to a database. Basically I want to load object c from the database upon initialization and still be able to get updates to the database afterwards. The problem is I tried doing this and I get the following initialization error.
org.springframework.beans.factory.BeanCreationException: Error creating bean with name defined in file
Instantiation of bean failed;
Could not instantiate bean class
Constructor threw exception; nested exception is java.lang.NullPointerException
Is this even possible since the dependency must be injected before the object B has been constructed, or how would I do this?
There are two solutions to your problem. You can in fact use constructor injection with Spring, but you might instead want to use a method annotated #PostConstruct. It'll get executed after all of the necessary injections have happened but before the bean is put into service (e.g., by being made available to another bean or to a servlet), and you can execute any code you like there with the knowledge that the bean is in a valid constructed state.
#Service("b")
class B {
#Autowired
#Qualifier("a")
A a;
SomeObject c;
public B(){}
#PostConstruct
private void initializeSomeObject() {
c = a.getSomeObject();
}
}
Beans are created first and then its dependencies are injected, that's why you're getting the NullPointerException. Try this:
#Service("b")
Class B{
A a;
SomeObject c;
#Autowired
#Qualifier("a")
public B(A a){
this.a = a;
c = a.getC();
}
}
If I have two classes like:
Class A {
public String importantValue = "stringvalue";
#Autowire
public B b;
}
#Component
#Scope("prototype");
Class B {
// This should be set automatically
// from IOC Container upon injection.
public String importantValueFromA;
}
Is this even possible? As soon as B class has been injected to A it should automatically set the value in B.
Do you want class A to do some setup on injected class B? That's simple:
#Service
class A {
private String importantValue = "stringvalue";
#Autowire
private B b;
#PostConstruct
public void initB() {
b.importantValueFromA = this.importantValue;
}
}
Obviously you cannot access b.importantValueFromA in A.A constructor because injection didn't yet happen. But #PostConstruct callback is guaranteed to be called after injection.
Another approach is to use setter injection, but it feels kind of hacky:
private B b;
#Autowire
public void setB(B b) {
this.b = b;
b.importantValueFromA = this.importantValue;
}
Two suggestions:
keep your fields private and use setters/methods to access them.
injecting prototype scoped bean to singleton bean might have some unexpected results. Enough to say only one instance of B will be created.
No. B is created before A (since A depends on B) so it will not update the value itself. You have to use a contructor injection:
Class A {
public String importantValue = "stringvalue";
#Autowire
public A(B b) {
b.importantValueFromA = this.importantValue;
}
}
How about doing something like this:
Declare your class B as a scoped proxy, which underlying will expose a proxy to A instead of the real B and will respect the prototype scope.
#Component
#Scope(value="prototype", proxyMode=ScopedProxyMode.TARGET_CLASS)
class B {
Then you can inject in an attribute of A in B this way:
#Value("#{a.importantValue}")
private String importantValueFromA;
Here is a full working example in a gist:
https://gist.github.com/3395329