Are Spring's #Autowired object reused? - spring

And if they are, How to stop that?

It depends on the scope of the bean being annotated. If it is of scope singleton, then it the same instance will be used everywhere in the Spring ApplicationContext. If it is of scope prototype, then a new instance will be used in each location.
<bean id="id" class="some.NewObject" scope="prototype"/>
<bean id="id2" class="some.AnotherNewObject" scope="singleton"/>
These bean definitions coupled with the following code will help to illustrate.
class Class1 {
#Autowired
some.AnotherNewObject obj;
}
class Class2 {
#Autowired
some.AnotherNewObject obj;
}
class Class3 {
#Autowired
some.NewObject obj;
}
class Class4 {
#Autowired
some.NewObject obj;
}
Class1 and Class2 will receive a reference to the same instance of some.AnotherNewObject. Class3 and Class4 will receive references to different instances of some.NewObject.
If you are using annotations and package scanning for configuration, then you can can use the #Scope annotation to specify your scope:
#Component
#Scope("prototype")
class NewObject {
...
}
#Component
#Scope("singleton")
class AnotherNewObject {
...
}

#Service
#Scope("prototype")
public class CustomerService
{}

Related

Spring Abstract class #Autowire null while using that field in subclass constructor

Following is the code:
public abstract class A {
#Autowired
public Provider provider;
}
#Component
public class B extends A {
B() {
provider.get();
}
}
Spring is throwing NullPointerException, while instantiating Bean of Class B.
I know #Autowired defined in Abstract class are injected, but don't know in which order they are injected.
Earlier my understanding was, While instance creation of B, Spring will autowire fields of all subclasses and then will create instance of B.
But here it seems, it overlooks the subclass concept while instance creation, and just scans B to identify #Autowire field.
Use #PostConstruct. Java Object Instantiation and Spring Dependency Injection are two different flows.
#Component
public class B extends A {
#PostConstruct
void init() {
provider.get();
}
}
If autowiring your constructors is an option the following can be helpful.
public abstract class A {
protected final Provider provider;
#Autowired
public A(Provider provider) {
this.provider = provider;
}
}
#Component
public class B extends A {
#Autowired
B(Provider provider) {
super(provider);
provider.get();
}
}
Note since the latest Spring Versions you do not need to annotate the constructor with #Autowire. If you do things right the spring framework auto-detects the constructor.

Java class xml vs java bean autowiring

In xml defined beans you can define two classes like this
<bean id="classA" class="ex.ClassA"/>
<bean id="classB" class="ex.classB"/>
Then in your java implementation you can autowire the constructor of one of the classes in example
public class ClassA {
#autowired
public(ClassB classB){
this.classB = classB;
}
Now how does one do that with java config beans since in example
#Bean
public ClassA classA(){
return new ClassB();
}
#Bean
public ClassB classB(){
return new ClassB()
}
the compiler would warn that Class a does not have any such constructor, how does one do that in java, with autowiring?
Thanks all
See http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-java-injecting-dependencies
Note that the ClassB bean is implicitly a singleton. The use of the annotation #Configuration on the Config class ensures that Spring returns the singleton instance of the ClassB bean in the classB() call.
#Configuration
public class Config {
#Bean
public ClassA classA(){
return new ClassA( classB() );
}
#Bean
public ClassB classB(){
return new ClassB();
}
}
Or you may prefer this approach (Spring 4.2.1+ required)
#Configuration
#Import(ClassA.class)
public class Config {
#Bean
public ClassB classB(){
return new ClassB();
}
}
#Component
public class ClassA {
#Autowired
public ClassA(ClassB classB) {
...
}
}
Pass the beans you want as parameters to the #Bean method, or use component scanning to create the dependent bean implicitly.

DRY Spring AnnotationConfig testing

So, I'm working on some Spring tests which require dependency injection using annotations:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(loader=AnnotationConfigContextLoader.class)
public class BeanTest {
#Autowired
private SomeService someService;
#Configuration
static class ContextConfiguration {
#Bean
public SomeService someService() {
return new SomeService();
}
}
}
I'd really like to not have to repeat this code in every test but my attempts to create a base class which contains the configuration:
#Configuration
class MyContextConfiguration {
#Bean
public SomeService someService() {
return new SomeService();
}
}
And deriving from it:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(loader=AnnotationConfigContextLoader.class)
public class BeanTest {
#Autowired
private SomeService someService;
#Configuration
static class ContextConfiguration extends MyContextConfiguration {}
}
Don't seem to work. Can anybody suggest a way to DRY this up?
Thanks!
You should be able to do this instead.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration
public class BeanTest {
#Autowired
private SomeService someService;
#Configuration
#Import(MyContextConfiguration.class)
static class ContextConfiguration {
....
}
}
Also, you don't need to mention AnnotationConfigContextLoader, Spring by convention will automatically pick up the static inner class annotated with #Configuration and use the appropriate ContextLoader
You can declare configuration classes in the the contextconfiguration-annotation. From the documentation.
ContextConfiguration
Defines class-level metadata that is used to determine how to load and configure an ApplicationContext for integration tests. Specifically, #ContextConfiguration declares the application context resource locations or the annotated classes that will be used to load the context.
Resource locations are typically XML configuration files located in the classpath; whereas, annotated classes are typically #Configuration classes. However, resource locations can also refer to files in the file system, and annotated classes can be component classes, etc.
example from the documentation.
#ContextConfiguration(classes = TestConfig.class)
public class ConfigClassApplicationContextTests {
// class body...
}

Passing parameters to #Configuration in Spring

I have a requirement of creating a prototype bean that's stateful, i.e. take parameters in constructor.
I tried to use #Configuration to create that bean, but found it doesn't work if I use a parameterized constructor...
Note that the parameters I want to pass are NOT spring beans...they are simple POJOs...so I can't autowire them.
So this is what I want to do -
#Configuration
public class MyClassFactory {
#Bean
public MyClass getMyClass(Pojo1 pojo1, Pojo2 pojo2) {
return new MyClass (pojo1, pojo2);
}
}
#Scope("PROTOTYPE")
public class MyClass {
public MyClass(Pojo1 pojo1, Pojo2 pojo2) {
...
}
#Autowired SomeService1 service1;
#Autowired SomeService1 service2;
...
}
Of course I can make MyClass applicationContextAware, and pick up services from it, rather than making it a prototype bean...but was wondering why above pattern is not allowed...

Problem with Autowiring & No unique bean

I have 2 classes (B,C) extends class A.
#Service
public class A extends AbstratClass<Modele>{
#Autowired
A(MyClass br) {
super(br);
}
#Service
public class B extends A{
#Autowired
B (MyClass br) {
super(br);
}
#Service
public class C extends A{
#Autowired
C (MyClass br) {
super(br);
}
But i have this message:
No unique bean of type [A] ] is defined: expected single matching bean but found 2: [A, B, moveModeleMarshaller]
I really cant get why i have this message & how to resolve even after reading Spring documentation.
Thanks in advance.
You should rewrite your class to something like this with the #Qualifier annotation.
#Service
#Qualifier("a")
public class A extends AbstratClass<Modele>{
#Autowired
A(MyClass br) {
super(br);
}
#Service
#Qualifier("b")
public class B extends A{
#Autowired
B (MyClass br) {
super(br);
}
#Service
#Qualifier("c")
public class C extends A{
#Autowired
C (MyClass br) {
super(br);
}
You must also use the #Qualifier annotation on the instance of type A you're autowiring the Spring bean into.
Something like this:
public class Demo {
#Autowired
#Qualifier("a")
private A a;
#Autowired
#Qualifier("b")
private A a2;
public void demo(..) {..}
}
If you don't like to have this Spring configuration in your production code, you have to write the dependency injection logic with XML or Java configuration instead.
You can also specify a default bean of type A with the #Primary annotation above one of your service classes that extends type A. Then Spring can autowire without specifying the #Qualifier annotation.
Since Spring will never try to guess which bean to inject, you have to specify which one or mark one of them with #Primary as long as its more than one bean of a type.
You are trying (somewhere else) to autowire a bean of type A. Something like:
#Autowired
private A beanA;
But you have 2 beans that conform to this.
You can resolve this by using #Resource and specifying which bean exactly:
#Resource("b")
private A beanA;
(where "b" is the name of the injected bean) or using the #Qualifier annotation.
Generally you will get this error when defined two beans with same class
<bean id="a" class="com.package.MyClass"/>
<bean id="b" class="com.package.MyClass"/>
if you address the above two line we have two beans with same class.
when you trying to autowire this class in any other classed you will get this type of error
You have two solutions
First Method
use qualifier by defining a bean id init
like this
#Autowired
#Qualifier("a")
MyClass a;
#Autowired
#Qualifier("b")
MyClass b;
Second Method
use JSR250 api(its a jar file you can put into your class path
Then do autowriring like below
#Resource("a")
MyClass a
#Resource("b")
MyClass a

Resources