When a bean is autowired, does it create multiple instances of the class?
Here's an example;
public class ClassA {
#Autowired
private ClassB classB;
public ClassB getClassB() {
return classB;
}
public void setClassB(ClassB classB) {
this.classB = classB;
}
// using ClassB in method 1
public void useClassBmethod1() {
// currently using autowired ClassB instance
classB.doSomething();
}
// using ClassB in method 2
public void useClassBMethod2() {
// need a new instance of ClassB but through the same autowired bean
ClassB classb = getClassB();
}
}
public class ClassB {
public void doSomething() {}
}
So my question is, does autowiring a bean know how to create a new instance of a bean when needed or this is left to the programmer to decipher?
Thanks for helping out.
It depends on attribute scope of bean tag. If scope="singleton" which is by default then each time you will get single instance and if scope="prototype" then you will get different instances. And it doesn't depend on autowire.
<bean class="ClassB" scope="prototype">
By using #Autowired you instruct classloader to associate any class instance available in container to associate with the callee. You need to make sure that you have made an entry to instantiate the bean in your config file like <bean id="test" class="xxx.Test" />. Also you might want to check scopes too.
If you have multiple instances of same class define with different names then with #Autowired you need to provide specific name that you want to use with the help of qualifier.
by default all beans are singleton so only one instance will be created, more about scopes http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/html/beans.html#beans-factory-method-injection
Related
Id, like to ask that what exactly a Qualifier annotation is doing on a Bean method? I thought it is the same as specifying a name inside the Bean annotation but a use-case proves otherwise:
The configuration:
#Bean
#Qualifier("myGroup")
public MyObject myObject1() {
return new MyObject("myObject1");
}
#Bean
#Qualifier("myGroup")
public MyObject myObject2() {
return new MyObject("myObject2");
}
#Bean
public MyObject myObject3() {
return new MyObject("myObject3");
}
The injection:
#Autowired
#Qualifier("myGroup")
private List<MyObject> myObjects;
The list myObjects will contain only myObject1 and myObject2, the ones that have the qualifier.
The bean names will be named by the method.
So my question would be, why, and how is this working?
This works because you're autowiring a list of MyObject. Autowiring multiple beans of the same class into a list containing that class is not an issue. I mean, it's different instances, yes but if you're autowiring a list of them then you should know why you're doing that.
If you do this then it won't work
#Autowired
#Qualifier("myGroup")
private MyObject myObjects;
because then myObject1 and myObject2 would both be qualified as autowiring candidate, which will throw Spring off. And since you put #Qualifier when autowiring, it only autowires beans that fit the name that's specified in the #Qualifier
I have a instance of a class that is created outside of Spring that I'd like to have access to Spring beans so that it may fire an event and be observed by Spring beans. I'm not using Spring web, my application is running from the command-line via spring boot.
The only option you have is to expose the Spring context of your application using a static method so that the object that is not managed by Spring can use it to get references to managed beans it needs.
Start with a wrapper for the context. Create a regular managed bean which required reference to the context in its constructor. The reference is assigned to a static class field, which also has a static getter:
#Service
class ContextWrapper {
private static ApplicationContext context;
#Autowired
public ContextWrapper(ApplicationContext ac) {
context = ac;
}
public static ApplicationContext getContext() {
return context;
}
}
Use the static getter to get access to context in the object which is not managed by Spring and get reference to beans using methods available in the context:
SomeBean bean = ContextWrapper.getContext().getBean("someBean", SomeBean.class);
// do something with the bean
Last thing you need is communication channel from Spring beans to non-managed object. For instance, the SomeBean can expose a setter which will accept the non-managed object as a parameter and store the reference in a field for future use. The object mast get references to managed beans using the static context accessor mentioned above and use the setter to make the bean aware of its existence.
#Service
class SomeBean {
// ... your bean stuff
private SomeClass someclass;
public void setSomeClass(Someclass someclass) {
this.someclass = someclass;
}
private void sendEventToSomeClass() {
// communicate with the object not managed by Spring
if (someClass == null) return;
someClass.sendEvent();
}
}
You can inject by constructor that spring beans, something like:
#Service
class Bean {
...
}
class NotBean {
private Bean bean;
public NotBean(Bean bean) {
this.bean = bean;
}
// your stuff (handle events, etc...)
}
I have the following components, in two different files:
#Component
public class Chauffeur {
Car car;
public Chauffeur(Car car){
this.car = car;
}
public void go(){
System.out.println("Chauffeur");
car.drive();
}
}
#Component
public class Car{
public void drive() {
System.out.println("Drive car");
}
}
the following configuration file:
#Configuration
#ComponentScan
public class DriveableConfiguration {
}
and the following test:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes=DriveableConfiguration.class)
public class DriveableTest {
#Autowired
Chauffeur chauffeur;
#Test
public void chauffeurTest(){
chauffeur.go();
}
}
All the classes above are in the same package and the test is passing.
In the test I annotated chauffer with #Autowired, which should mean that the Spring container looks after the creation of the instance of Chauffeur without the developer needing to explicitly instantiate it.
Now, the constructor for Chauffer needs an instance of Car, so there is no default constructor for that class. Nonetheless the container creates it, injecting the required instance in the constructor.
Is the #Autowired saying to the container to instantiate the element with whatever (Components, Beans) it can provide, included parameters in the constructor? If so, in what case is it needed to use #Autowired to annotate a constructor?
Only if you use Spring 4.3+. In such a case #Autowired on constructor is optional if you have one non default constructor.
You can check the example here.
So as of 4.3, you no longer need to specify an explicit injection annotation in such a single-constructor scenario. This is particularly elegant for classes which otherwise do not carry any container annotations at all, for example when programmatically registered
For versions lower than 4.3 you will an exception will be thrown:
the container will throw an exception looking for a default
constructor, unless you explicitly indicate autowire mode
‘constructor’ in your bean definition setup (e.g. in an XML )
I have a bean that looks like this:
#Component
#Scope("session")
public class AlarmChartSettingsBean implements Serializable {
...
Inside this bean i inject another bean like this:
#Inject
private SessionInfoBean sessionInfoBean;
Then i call the injected bean inside the constructor of the first bean like this:
public AlarmChartSettingsBean() {
String atcaIp = sessionInfoBean.getNwConfigBean().getAtcaIP();
}
The problem is that the injected bean is null. So the question is when is that bean injected? Can i use it inside the constructor or i should use it after the bean has been constructed?
The constructor of a Spring bean is called before Spring has any chance to autowire any fields. This explains why sessionInfoBean is null inside the constructor.
If you want to initialize a Spring bean, you can:
annotate a method with #PostConstruct:
#PostConstruct
public void init() {
String atcaIp = sessionInfoBean.getNwConfigBean().getAtcaIP();
}
implement InitializingBean and write the initialization code inside the afterPropertiesSet method:
public class AlarmChartSettingsBean implements Serializable, InitializingBean {
#Override
void afterPropertiesSet() {
String atcaIp = sessionInfoBean.getNwConfigBean().getAtcaIP();
}
}
The #Inject on a Field will autowire after the constructor has been called.
Note: In some Spring-Apps the #Inject may not work, use #Autowire instead.
I have recently learned concept of autowiring in spring. When I was trying to understand in which particular scenarios spring autowiring can be useful
I came up with the below two reasons from one of the questions asked in our stakoverflow forum.
1.I wanted to read values from a property file and inject them into a bean. Only way I could figure out how to do this at start up of my app was to
wire the bean in XML (and inject the properties.) I ended up using the "byName" attribute (because the bean was also marked as #Component) and then
used #Autowired #Qualifier("nameIChose") when injecting the bean into another class. It's the only bean I've written that I wire with XML.
2.I've found autowiring useful in cases where I've had a factory bean making another bean (whose implementation class name was described in a system
property,so I couldn't define the all wiring in XML). I usually prefer to make my wiring explicit though;
Can any body please give me some code snippet example of the above situations that would make my understanding of autowiring more clearer?
Here is an example of injecting properties into a bean.
Using field injection:
#Component
public class YourBean {
#Value("${your.property.name}")
private String yourProperty;
}
Using constructor injection:
#Component
public class YourBean2 {
private String yourProperty;
#Autowired
public YourBeans2(#Value("${your.property.name}") String yourProperty) {
this.yourProperty = yourProperty;
}
}
The following is a super simple example of autowiring various beans
#Component
public class Foo {
public void doSomething() {
}
}
#Component
public class Bar {
private Foo foo;
#Autowired
public Bar(Foo foo) {
this.foo = foo;
}
public void doSomethingElse() {
foo.doSomething();
}
}
In the previous example, no XML configuration of Foo and Bar needs to be done, Spring automatically picks up the beans because of their #Component annotation (assuming of course that component scanning has been enabled)