Singleton and Prototype in one Container - spring

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;

Related

How can I create the spring bean after all other beans?

For example, I have 3 beans in my spring configuration: A, B, C. And I want to create bean B and C as usual. And than (when all others beans were created) I want to ask spring to create bean A.
Any suggestion ?
Thanks.
Spring framework triggers a ContextRefreshedEvent once the contexts has been fully refreshed and all the configured beans have been created.
You could try to create a listener to catch that event and initialise bean A.
#Component
public class ContextRefreshedEventListener implements
ApplicationListener<ContextRefreshedEvent> {
#Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
// Init your bean here
}
}
You should try #DependsOn adnotation
For example
<bean id="beanOne" class="ExampleBean" depends-on="manager,accountDao">
<property name="manager" ref="manager" />
</bean>
<bean id="manager" class="ManagerBean" />
<bean id="accountDao" class="x.y.jdbc.JdbcAccountDao" />
I know it's not really a bean ordering answer, but maybe you can achieve your goal with a #PostConstruct method that will be called just after a bean is constructed, dependencies are injected and all properties are set.
best nas
Easier way to do this would be using #Lazy annotation to your bean. This makes your bean do not get initialized eagerly during context initialization. In simple words,your bean will get created when you ask for it, not before.
#Bean
#Lazy
public A beanA() {
//some code here
}

Constructor injection in Spring

I'm working on a code where a class A is constructing an object of class B using parameterized constructor of class B. As of now, class B is not yet spring injected. The requirement is that I should always have a new non-singleton object of class B. The code somewhat looks like this:
class A{
private List<ClassB> classBList = new ArrayList<ClassB>();
void parseInfo(File f, Element e){
ClassB b = new ClassB(this,f,e);
classBList.add(b);
}
}
How should my spring-config look like if i have to inject class B using spring?
Define the bean as prototype
<!-- A bean definition with singleton scope -->
<bean id="classBBean" class="ClassB" scope="prototype"/>
Use applicationContext getBean method to create bean each time by passing arguments.
class A implements ApplicationContextAware{
private List<ClassB> classBList = new ArrayList<ClassB>();
#Autowired
private ApplicationContext appContext;
void parseInfo(File f, Element e){
ClassB b = (ClassB)appContext.getBean("classBBean",new Object[]{this,f,e});
classBList.add(b);
}
}
If I understand correctly, you are asking about Spring scopes
Basically, you need to declare your bean with scope prototype if it's a general spring application
<!-- A bean definition with singleton scope -->
<bean id="..." class="..." scope="prototype">
<!-- collaborators and configuration for this bean go here -->
</bean>
or request, if it's a web spring application
<!-- A bean definition with singleton scope -->
<bean id="..." class="..." scope="request">
<!-- collaborators and configuration for this bean go here -->
</bean>
For more examples look at
http://www.tutorialspoint.com/spring/spring_bean_scopes.htm

Unable to Autowire a bean of type String

I have a bean as defined below which I want to autowire in to a Class which is defined as a bean in the Spring context file. But its not working, Strangely the other object bean types autowired in the same class are being autowired correctly.
Bean to Autowire is as below :-
<bean id="stringToAutowire" class="java.lang.String">
<constructor-arg value="true" />
</bean>
Class where its to be Autowired is :- I have tried annotating it with #Component .But no success.
public class AService {
#Autowired
private BDao bDao;
#Autowired
private String stringToAutowire;
........
}
context file is as :-
<context:annotation-config/>
<context:component-scan base-package ="PKG "/>
<bean id="aService" class="AService"/>
<bean id="bDao" class="BDao"/>
<bean id="stringToAutowire" class="java.lang.String">
<constructor-arg value="true" />
</bean>
In the Spring documentation:
http://docs.spring.io/spring/docs/3.0.x/spring-framework-reference/html/beans.html#beans-autowired-exceptions
There is this text "You cannot autowire so-called simple properties such as primitives, Strings, and Classes (and arrays of such simple properties). This limitation is by-design."
I have not found an exact specification of what happens in this case. In my experience Autowire of String properties is unreliable. Sometimes works, sometimes not. So I recommend avoiding autowire of string values.
In your case you are using both Autowire and constructor-arg. They are separate mechanisms. Only one is required.
Ditch Autowire for String.
Add a constructor to AService that takes, as the first argument, a string to assign to "stringToAutowire". The "constructor-arg" will specify what to pass for this constructor argument.
try using below:
#Autowired
#Qualifier("stringToAutowire")
private String someString;
You can not autowire simple properties such as primitives, Strings, and Classes (and arrays of such simple properties) and explicit dependencies in property and constructor-arg settings always override autowiring.
So drop #Autowired annotation from stringToAutowire and use with property.

How to use the same bean in two different spring contexts?

I have two spring contexts and I need to use the same bean in both of them. Is there a way to share a bean between two contexts without making a parent context?
I don't think what you want is a good idea. If you have the same bean in two contexts, then which context manages the bean's lifecycle? By having a common parent owning the bean, you have a clear, unambiguous answer to that important question: the bean belongs to the parent context.
Now, if you know the beans will belong to context A and only want to bind them to some name in context B, I guess you could hack some kind of "guest" bean factory or whatever, that does something like:
Java:
public class GuestBeanFactory {
private ApplicationContext guestBeanContext;
#Inject
public void setGuestBeanContext(ApplicationContext guestBeanContext) {
this.guestBeanContext = guestBeanContext;
}
private String guestBeanName;
#Inject
public void setGuestBeanName(String guestBeanName) {
this.guestBeanName = guestBeanName;
}
public Object getBean() {
return guestBeanContext.getBean(guestBeanName);
}
}
applicationContext.xml:
<beans ...>
...
<bean id="myGuestFactory" class="GuestBeanFactory" scope="singleton">
<property name="guestBeanContext" ref="...get a reference to the guest bean and inject it here" />
<property name="guestBeanName" value="name-of-this-bean-inside-guestBeanContext"/>
</bean>
<bean id="myGuestBean" factory-bean="myGuestFactory" factory-method="getBean"/>
...
</beans>
This way, guestBeanContext manages name-of-this-bean-inside-guestBeanContext, but the "host" context can access that bean using the name myGuestBean.

Getting an instance of a bean excplicitly in runtime

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.

Resources