With below XML configuration
<context:property-placeholder location="constants.properties"/>
<bean id="MyDBDetails"
class="itsmine.springcore.MyDBDetails" scope="singleton">
<property name="fName" value="${fName}" />
<property name="lName" value="${lName}" />
<property name="age" value="${age}" />
</bean>
I created a bean in my main using below 2 options:
1) using ClassPathXmlApplicationContext
2) using bean factor
The dynamic values got set when bean created using ClassPathXmlApplicationContext, but not when created using bean factory.
Could you please suggest how to make it work using bean factory ?
Thanks in advance.
When using XML declaration for bean properties, the property-placeholder is registered as a Bean Factory Post Processor for the IoC container, thus you will have the properties values available.
However, when instantiating beans programatically through a BeanFactory, this factory won't be aware of the properties values unless your configure a `` as its post processor:
BeanFactory factory = /* your factory initialized */;
PropertyPlaceholderConfigurer cfg = new PropertyPlaceholderConfigurer();
cfg.setLocation(new FileSystemResource("constants.properties"));
cfg.postProcessBeanFactory(factory);
EDIT
Note that the org.springframework.beans.factory.config.PropertyPlaceholderConfigurer#setLocation accepts a org.springframework.core.io.Resource as its argument, i.e. you can use any of the its concrete sub-implementation depending on your needs:
org.springframework.core.io.FileSystemResource: An implementation supporting file handles.
org.springframework.core.io.ClassPathResource: An implementation for classpath resources.
org.springframework.core.io.InputStreamResource: An implementation for an InputStream...
Related
Is there a way to get sessionFactory object from spring-hibernate combined XML file without using it (SessionFac..) as a instance variable?
If you are using pure XML and define a SessionFactory bean, you can inject it into another XML defined bean as follows:
<bean id="myService" class="com.company.service.MyService">
<!-- reference the sessionFactory bean by value -->
<property name="sessionFactory" value-ref="sessionFactory"/>
</bean>
If you have defined the SessionFactory bean in XML and then want to inject it using annotations, you simply need to add an #Autowired annotation to the field, setter, or the constructor where you are passing a SessionFactory variable.
I have a doubt about the number of instances that will be created in the scenario mentioned below, when Spring Framework is used:
The bean configuration is like this
<bean id="a" class="A">
<property name="b" ref="b"/>
</bean>
<bean id="b" class="B" scope="session"/> or
<bean id="b" class="B" scope="prototype"/>
By default, bean "a" has singleton scope. So there is a singleton bean with a reference to a bean with session scope or prototype scope.
In this case, if there are 2 simultaneous requests to the application, then how many instances of A will be created and how many instances of B will be created?
It will be of great help if anyone can explain how this works.
Thanks,
Divya
The singleton scope
When a bean is a singleton, only one shared instance of the bean will be managed, and all requests for beans with an id or ids matching that bean definition will result in that one specific bean instance being returned by the Spring container.
To put it another way, when you define a bean definition and it is scoped as a singleton, then the Spring IoC container will create exactly one instance of the object defined by that bean definition. This single instance will be stored in a cache of such singleton beans, and all subsequent requests and references for that named bean will result in the cached object being returned.
The session scope
With the above bean definition in place, the Spring container will create a brand new instance of the bean , for the lifetime of a single HTTP Session.
According to Spring framework reference, a different approach needs to be followed in cases where a class which "lives longer"(singleton bean in this case) needs to be injected with another class having a comparatively shorter life-span(session-scoped bean). The approach is different for prototype & singleton scope though.
In your XML, what we want is that the singletonBean instance should be instantiated only once, and it should be injected with sessionBean. But since sessionBean is session-scoped(which means it should be re-instantiated for every session), the configuration is ambiguous(as the dependencies are set at instantiation time and the session scoped value can change later also).
So instead of injecting with that class, its injected with a proxy that exposes the exact same public interface as sessionBean. The container injects this proxy object into the singletonBean bean, which is unaware that this sessionBean reference is a proxy. Its specified by writing this tag in the sessionBean:
<aop:scoped-proxy/>
XML Configuration:
<bean name="singletonBean" class="somepkg.SingletonBean">
<property name="someProperty" ref="sessionBean"/>
</bean>
<bean name="sessionBean" class="somepkg.SessionBean" scope="session">
<aop:scoped-proxy/>
</bean>
When a singletonBean instance invokes a method on the dependency-injected sessionBean object, it actually is invoking a method on the proxy. The proxy then fetches the real sessionBean object from (in this case) the HTTP Session, and delegates the method invocation onto the retrieved real sessionBean object.
Alse please refer this for more info.
Singleton beans with prototype-bean dependencies
Lookup Method Injection
When you use singleton-scoped beans with dependencies on prototype beans, be aware that dependencies are resolved at instantiation time. Thus if you dependency-inject a prototype-scoped bean into a singleton-scoped bean, a new prototype bean is instantiated and then dependency-injected into the singleton bean. The prototype instance is the sole instance that is ever supplied to the singleton-scoped bean.
However, suppose you want the singleton-scoped bean to acquire a new instance of the prototype-scoped bean repeatedly at runtime. You cannot dependency-inject a prototype-scoped bean into your singleton bean, because that injection occurs only once, when the Spring container is instantiating the singleton bean and resolving and injecting its dependencies.
<!-- a stateful bean deployed as a prototype (non-singleton) -->
<bean id="command" class="fiona.apple.AsyncCommand" scope="prototype">
<!-- inject dependencies here as required -->
</bean>
<!-- commandProcessor uses statefulCommandHelper -->
<bean id="commandManager" class="fiona.apple.CommandManager">
<lookup-method name="createCommand" bean="command"/>
</bean>
Lookup method injection is the ability of the container to override methods on container managed beans, to return the lookup result for another named bean in the container. The lookup typically involves a prototype bean as in the scenario described in the preceding section. The Spring Framework implements this method injection by using bytecode generation from the CGLIB library to generate dynamically a subclass that overrides the method.
Refer lookup method injection.
Follow for more detailed example and information.
If we use the way as mentioned in question spring IOC will create always return the same object as singleton, In order to inject prototype bean inside singleton we have two way
1) Lookup method injection
2) Scoped Proxies
see more detail here
First of all, I don't think it is valid to define a bean, both with session and prototype scopes at the same time with the same bean id.
How many instances created for singleton bean referring to a prototype bean?
In your case: one
In general: depending on how you access the bean:
One
#Component
class MySingletonBean{
#Autowired
MyPrototypeBean b;
}
Two
#Component
class MySingletonBean{
#Autowired
MyPrototypeBean b;
#Autowired
MyPrototypeBean bSecondInstance;
}
Or more
#Component
class MySingletonBean{
#Autowired
javax.inject.Provider<MyPrototypeBean> providerOfB;
void accessMultipleInstances(){
MyPrototypeBean bInstance1 = providerOfB.get();
MyPrototypeBean bInstance2 = providerOfB.get();
MyPrototypeBean bInstance3 = providerOfB.get();
//.....
}
}
Note: MyPrototypeBean is considered to have been marked with: #Scope(scopeName = ConfigurableBeanFactory.SCOPE_PROTOTYPE). If you omit it ,then in all the above cases you will reference the same singleton instance.
Regarding session-scoped bean:
One per session.
According to this answer spring will automatically create a proxy which targets different instance depending on the session.
This means that in all the above cases you will get access to the same instance while you are on the same session.
Regarding the provided xml config:
To me it would be more meaningful something like this:
<bean id="a" class="A">
<property name="b" ref="b"/>
<property name="b2" ref="b2"/>
</bean>
<bean id="b" class="B" scope="session"/> or
<bean id="b2" class="B" scope="prototype"/>
In which case you would get one instance per session for b and one and only instance for b2 because you use it from a singleton and you don't use the provider or some similar pattern.
Is it possible to create to bean with same id with same class with different property in spring ? Like:
<bean id ="a" class= "com.tofek.A"
<property message = "khan"/>
</bean>
<bean id = "a" class = "com.tofek.A"
<property message="tofek"/>
</bean>
As per my understanding it will create, but while fetching the bean using getBean() method it will give exception like NoBeanDefinitionFoundException.
Please correct my understanding if I'm wrong?
Make sure your spring context is loaded sucessfully.
Answering your question. You can have two identical bean definitions in two different sprintContext configurations.
The bean from second context will override bean created by first one.
For example :
context1.xml
<bean id="bean1" class="org.springframework.beans.TestBean"/>
context2.xml
<bean id="bean1" class="org.springframework.beans.TestBean"/>
then, the bean from context2.xml will override bean created by contex1.xml.
It of course depends on order of creating spring contexts. The laters overrides the ones made before.
You can use getBean() to fetch bean by type or name. In this case, both bean have same id's and types, the spring wouldn't know which one you want to fetch.
Let's say I have two modules. One is core and another is core dependent implementation module.
Core is a jar file for that dependent implementation module war.
In the core I have a bean defined like
<bean id="x" class="com.pokuri.X">
<property name="y" ref="y"/>
<property name="z" ref="z"/>
</bean>
And that class has a method as follows
public class X{
public void doSomeJob(){
.......
}
}
this method is being called from some core classes. Now I need to alter the logic in that doSomeJob() method of X as per my core dependent implementation. So, I create a class like this
public class ExtX extends X{
#override
public void doSomeJob(){
// changed logic
}
}
and defined the bean with same id in another application context xml file like this.
<bean id="x" class="com.pokuri.ExtX">
<property name="y" ref="y"/>
<property name="z" ref="z"/>
</bean>
and we are building application context using contextConfigLocation context parameter in web.xml specifying value as classpath:springfolder.
But in the core logic I am getting core bean instance only(i.e X instance) not ExtX. How can we override that bean definition and let system start using new extend bean definition?
And I heard that with same ID in different application context files will override first loaded bean definition with later loaded bean definition. Is there any priority kind of attribute on bean definition to let ApplicationContext use highest priority one to consider over low priority one when beans with same ID were found.
One way of overriding the bean definition is what you have indicated - to define it with the same id multiple times and the last bean definition with the same id is the one which takes effect. So if you ensure that ExtX is the last one loaded up, it should just work, and to ensure this you can do this in your war file, instead of loading up by saying classpath:springfolder, you can explicitly import the core configuration in your war's Spring config file and then override the bean this way:
<import resource="core-resource.xml"/>
<bean id="x" class="com.pokuri.ExtX">
<property name="y" ref="y"/>
<property name="z" ref="z"/>
</bean>
This will ensure that your overridden bean is the one which takes effect.
There is no priority/order field that you can make use of here though - if you want you can load up all bean definitions of a type by providing Map<String,X> as a parameter, and sort it by expecting an order property and use it that way, but there is lot more work to it.
A second approach is described here: Overriding the bean defined in parent context in a child context
How can I create a bean of type Class?
I found a way using getClass() but that requires an instance and cannot be used via factory-method since it is not static. It also requires an extraneous bean be created for this express purpose:
<bean id="foo" class="Foo" />
<bean id="fooClass" factory-bean="foo" factory-method="getClass" />
This isn't so bad if the Foo class is easy to construct, but what if the constructor has required parameters?
I then need to create a Set of Class to wire into another bean via a property. I would create the Set such as:
<util:set id="classSet">
<ref local="fooClass"/>
</util:set>
If you really wanted to do what you describe, then you can do it like this:
<bean id="myClass" class="java.lang.Class" factory-method="forName">
<constructor-arg value="com.MyClass"/>
</bean>
But as #ChssPly76 said, if you want to inject it into another bean, you only need inject the class name, and Spring will auto-convert it into a class instance for you.
Why would you? Can you provide an example where that's actually needed?
If you only need this as a dependency (e.g. some other bean has a property of type Class), Spring's built-in ClassEditor property editor would convert a regular string into a Class instance with that name for you:
<property name="someClass" value="java.lang.String"/>
The above would result in setSomeClass(Class clazz) setter being called on the bean whose property that is.