Getting an instance of a bean excplicitly in runtime - spring

I have a case where I have a bean (let's call it A) which needs some other bean (B).
This B is retrieved from a static method of a class using MethodInvokingFactoryBean.
This static method depends on the state of the system and will work after the web application is loaded.
I need to access the B only in runtime (no interaction in the constructor).
How can I configure the A to autowire bean B and only initialize it the first time A requires it?
Is using getBean on the Application context the only way?
Thanks!
*Edit - Added some xmls :) *
This is the definition of bean B.
<bean id="api" class="com.foo.API"/>
<bean id="B" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean" lazy-init="true">
<property name="targetObject" ref="api"/>
<property name="targetMethod" value="getFactory"/>
<qualifier value="myQualifer"/>
</bean>
This is the definition of bean A.
<bean id="resources.someRESTResourceA" class="com.foo.MyRestResource"/>
I can't use Autowire to wire B into A because it will initialize it (B) on A's construction.
B's targetMethod will only work after the web app has been initialized.
I can use ApplicationContext.getBean("B") inside A, but it's not elegant and will be a problem with unit testing unless I do the following (which is also not desired):
public BInterface getB() {
if (b == null) {
b = ApplicationContext.getBean("B");
}
return b;
}

you should lazily initialize bean A.
<bean id="A" class="demo.A" lazy-init="true">
<property name="b" ref="B"/>
</bean>
You still need to retrieve the bean A from the Spring container when you need it with the getBean() method. It's easily accesible with the ApplicationContextAware interface.
If you autowire bean A into an another bean and that bean is retrieved before bean B is constructed, the Spring container will create bean A at the time it's injected as a property to the another bean.

Related

Singleton and Prototype in one Container

If there are two bean, and the bean b1 the scope is singleton, bean b2 the scope is prototype.In this case if the container is started then how many beans are created and to which scope it will go.
Two beans shall be created. One singleton and the other prototype.
If you are talking about two beans of same class, then also the scenario is same.
When you shall autowire the beans you would have to provide a qualifier attribute.
eg:
<bean id="a" class="package.classname" scope="prototype"/>
<bean id="b" class="package.classname" scope="singleton" />
During autowiring:
#Autowired
#Qualifier(id="a")
public package.classname instance1;
#Autowired
#Qualifier(id="b")
public package.classname instance2;

Spring Core-Setter Injection

I need help regarding mechanism of setter injection in Spring 3.0
Following is my code
package com.common;
class B{
public B(){}
}
class A{
B b;
public A(){}
public void setB(B b){
syso("I am in setter of B");
}
}
In XML,I have,
<bean id="A" class="com.common.A">
<property name="b" ref="B" />
</bean>
<bean id="B" class="com.common.B">
Now,my question is, How does spring container knows that it has to inject dependency through setB(B b) method? What if I change name of setter as newSetB(B b)? I hope I have made my doubt clear.
whenever you have something like this in your property file
<bean id="A" class="com.common.A">
<property name="b" ref="B" />
</bean>
spring container by default searches for setter of that property i.e setPropertyName() after invoking a no-argument constructor of that class whose bean is being prepared, and as it confines to JavaSpecification it searches for method named as setPropertyName()
You can verify this by chaning the name of method or by removing the method entirely
you will get the exception telling that, No Public setter found for that particular property
hope this helps!
Good luck!
The mapping here happens in this way.
Lets say we have following bean
<bean id="A" class="com.common.A">
<property name="testProperty" ref="B" />
</bean>
Spring container tries to get set method as setTestProperty(), if not found it will through an error.
Hope it helps - Cheers !
when ever SpringContainer reads the xml file and finds this
<bean id="A" class="com.common.A">
<property name="b" ref="B"/>
</bean>
<bean id="B" class="com.common.B"/>
firstly it creates object for Bean A, after that it initializes the member variables here "public B b", b is member variable for Bean class A, so it searches for setter method setB(B b) if it finds it sets else if NO setB(B b) SETTER Method is FOUND (OR) SETTER Method named DIFFERRENTLY ex: newSetB(B b) it throws exception as
Invalid property 'b' of bean class [com.common.A]: Bean property 'b' is not writable or has an invalid setter method.
setter methods convention for SpringContainer is setPropertyname()

With constructor autowiring Spring does not throw an exception when there are multiple implementation types

There are interfaces Work and You. There are implementation types WorkImpl and YouImpl and YouImpl2.
I use constructor autowire to inject a You implementation instance in a WorkImpl instance.
Because there are multiple You implementations types, I thought Spring would throw an exception. But Spring instantiates an instance of one of the implementation types, in my case it was YouImpl. This is what I do not understand.
The configuration file is partly,
<bean
id="work"
class="my.test.own.spring_book.WorkImpl"
autowire="constructor"
>
<property name="age" value="52"/>
<property" name="name" value="Foo Bar"></property>
</bean>
<bean
id="you"
class="my.test.own.spring_book.YouImpl"
>
</bean>
<bean
id="you2"
class="my.test.own.spring_book.YouImpl2"
>
</bean>
WorkImpl has one constructor,
public WorkImpl(You you) {
this.you=you;
}
There are few types of autowiring using configuration approach:
byName
byType
constructor
autodetect:- Similar to byType, but type applies to constructor arguments.
Spring container looks at the constructor of the beans on which autowire attribute is set to byType in the XML configuration file. It then tries to match and wire a property if its type matches with exactly one of the beans name in configuration file.
<bean id="you" class="my.test.own.spring_book.YouImpl">
</bean>
<bean id="you2" class="my.test.own.spring_book.YouImpl2">
</bean>
It will match with you as name of parameter used in constructor is you
public WorkImpl(You you) {
this.you=you;
}
In order to avoid this you can use autowire-candidate="false" hence that bean will not take part in autowiring
<!-- This bean will not be injected-->
<bean id="you" class="my.test.own.spring_book.YouImpl" autowiring-candidate="false">
</bean>
<bean id="you2" class="my.test.own.spring_book.YouImpl2">
</bean>
Above is the answer of your question. But I will try to explain more so I can use this answer for future if I forget.
Now suppose you don't give id attribute to the bean or value of id attribute is different than the constructor parameter name.
<bean id="you1" class="my.test.own.spring_book.YouImpl" autowiring-candidate="false">
</bean>
<bean id="you2" class="my.test.own.spring_book.YouImpl2">
</bean>
Spring container searches any bean with type You, yes found two. Do next step
Spring container sees any bean with name(i.e id="you") you. No
It throws exception Unsatisfied dependency Injection
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'work' defined in class path resource [autowire-contructor.xml]: Unsatisfied dependency expressed through constructor argument with index 0 of type
[my.test.own.spring_book.You]: : No unique bean of type [my.test.own.spring_book.You] is defined: expected single matching bean but found 2: [you1, you2]; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException

How can i use a specific proprety for each bean call in Spring

I'm developing an application using spring . I have a bean that i need to call multiple times but for each call i need to change the properties values dynamically . Is there a way to do this .
I had an idea to set the bean properties as an array ,in eatch array i put the parameters that i want to use . For example array[0] contains the params of the first call , array[1] params of the second call,... is it possible to do that ?
Here is a code sample :
<bean class="Dummy2">
<!-- or a list of values -->
<property name="foos">
<util:list>
<value>A,b,c</value>
<value>X,y,z</value>
<value>1,2,3</value>
<value>7,8,9</value>
</util:list>
</property>
</bean>
the setter
#Override
public void setFoo(list<String[]> args) {
...
}
If any one have a better idea or a usefull idea i will be grateful
Thank You
This is the propreties of the bean that calls the beans
<property name="activities">
<list>
<ref bean="1"/> //Calling bean 1
<ref bean="2"/> //Calling bean 2
<ref bean="1"/> //Calling bean 1 again
<ref bean="2"/>//Calling bean 2 again
<ref bean="2"/>
</list>
</property>
i need to use different parameters for each call (call the setter with different values)
Would using Spring's PostConstruct annotation on an initialiser method on your 'master' bean be useful? You could use simple setter methods to inject both the list of beans and the list of configurations into the master bean, and in the init method (annotated with #PostConstruct) configure each bean correctly.
http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/beans.html#beans-postconstruct-and-predestroy-annotations
Are you familiar with AOP you can use aspect to do this using #Before Advice to set your method properties before calling it

getting new bean instances of referencing beans every time

I have two queries ...
1) I have a query that beans are intialized in the spring container itself when the spring container is intialiazed and before the call is made to the get bean() method , this is the default behavior , how can I configure the application in such way that bean should be initalized in container only when a call is made of getbean() is made, shall we declare the bean as prototype to achieve this.
2) second query is that first please go through the below example first...
<beans>
<bean id="triangle" class="Demo.Triangle" scope="singleton" >
<property name="pointA" ref="zeropoint"/>
<property name="pointB" ref="firstpoint"/>
<property name="pointC" ref="secondpoint"/>
</bean>
<bean id="zeropoint" class="Demo.Point" scope="prototype" >
<property name="x" value="10" />
<property name="y" value="20" />
</bean>
<bean id="firstpoint" class="Demo.Point" scope="prototype" >
<property name="x" value="10" />
<property name="y" value="20" />
</bean>
<bean id="secondpoint" class="Demo.Point" scope="prototype">
<property name="x" value="10" />
<property name="y" value="20" />
</bean>
As indicated above that triangle bean is singleton and it references bean are protoype now when I access singleton the other refernces beans zeropoint,firstpoint and secondpoint are also initaizes only once with respect to triangle but Here I want that every time new instance of these three beans to be get created when the triangle bean is fetched , Please advise how that is achieable. is it achievable through my pojo implementing ApplicationContextAware interface, Please advise
Instead of relying on Spring infrastructure (BeanFactoryAware) I recommend trying lookup method feature:
abstract class Triangle {
public abstract Point createZeroPoint();
public abstract Point createFirstPoint();
public abstract Point createSecondPoint();
public void foo() {
Point p0 = createZeroPoint();
Point p1 = createFirstPoint();
Point p2 = createSecondPoint();
}
}
Every time you call create*Point() abstract method, it creates new instance of Point. But how do you implement this method and how does it know which bean to return? Spring implements this for you!
<bean id="triangle" class="Demo.Triangle" scope="singleton">
<lookup-method name="createZeroPoint" bean="zeropoint"/>
<lookup-method name="createFirstPoint" bean="firstpoint"/>
<lookup-method name="createSecondPoint" bean="secondpoint"/>
</bean>
Check out the comprehensive documentation: 4.4.6.1 Lookup method injection.
Its called Lazy loading
<bean id="myBean" class="a.b.MyBean" lazy-init="true"/>
First note that your firstpoint and secondpoint beans don't have a valid scope definition (you missed the scope=)
Prototype scope means that every bean that requires a prototype bean gets its own instance. If would define multiple triangles which all have a dependency to zeropoint every triangle would a separate zeropoint instance.
If you need new point instances inside your triangle class (e.g. every time you call a method of triangle) the best way is to receive instances directly from the bean factory:
E.g.
class MyClass implements BeanFactoryAware {
private BeanFactory beanFactory;
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
public void doSomethingThatRequiresNewInstance() {
Triangle t = beanFactory.getBean("zeropoint", Triangle.class);
// because zeropoint is defined as prototype you get a new instance everytime you call getBean(..)
}
}

Resources