I am using Spring3 with xml based configuration.
The problem is when the IOC container starts it loads/caches all the properties/fields defined in com.dao.MyDAOFactory class. I want to tell spring that only load/cache specific properties/fields.
The bean declaration is given below
<bean id="daoFactory" class="com.dao.MyDAOFactory" ></bean>
Can any one help me ?
You can use the lazy-init attribute to defer the loading of your beans, but eventually all of them will be loaded.
Also keep this in mind that if a non-lazy singleton bean depends on one or more lazy beans, the lazy beans will be loaded at startup.
Related
Is there a way to enforce the initialization of a Spring Bean in cases that the reference of the bean is never explicitly used or even requested in the ApplicationContext?
<bean class="foo.bar.FooBar>
<property name="fooBar" ref="foo.bar.reference"/>
</bean>
This bean is meant to do things inside, get's properties passed by IoC but it is never used by any other bean which implies that the it's reference is nowhere else configured.
My problem is, that this bean seems not to be initialized because of that.
I tried <bean .. lazy-init="false"/> but this did not do the trick.
How can ensure the bean is going to be initialized?
Since I cannot modify the application context, I would need a way doing it just in the XML configuration.
I'm not sure, but maybe you could try to use the singleton=true property for that bean - in non-singleton mode, the bean would be instatiated only if requested by the application.
http://docs.spring.io/spring/docs/1.2.9/reference/beans.html
(see 3.2.5)
Edit: Can you add some logging to ctor to see if it's called? If not, could you add an init-method and log something there?
I came across below statement from Spring MVC documentation:
Upon initialization of a DispatcherServlet, Spring MVC looks for a
file named [servlet-name]-servlet.xml in the WEB-INF directory of
your web application and creates the beans defined there, overriding
the definitions of any beans defined with the same name in the global
scope.
Please help me in understanding this statement.
As global scope is used for portlet based applications, then why a developer wants to configure like this in normal Spring MVC applications?
I don't think the term "global scope" here means the global scope bean like singleton, prototype, request, session and global. I believe the global scope here means the scope of the bean context.
In Spring MVC, there are 2 scopes of bean can be defined. The first one is at servlet context level which I believe is what it meant by "global scope" in the above statement. The second one is at servlet level where the bean defined at this level will take priority when resolved by other bean in servlet level.
The beans in servlet level will be able to resolve beans in servlet context (global) level but not the other way round.
Spring MVC provides options to configure multiple Context based on number of DispacthServlet Configuration .
For example
Consider you have two modules with in your application and url pattern starts as module1/* and module2/* . And you want to keep two different context ( always declarations in *context.xml is private to the context ). So you would be creating two dispatchServlet and provide two different servletname and url pattern. Now you have two Spring context which has specific declartions and which is not visible to other. But still you may wanted to declare some application wide beans such as persistentManager / Logger instance and so. for those case you can keep seperate config as root-context.xml and keep the generic declartions in that root. Which is considered here as "GLOBAL SESSION" Now this Global Session beans scope can be different scope based on configuration. And the bean configured in Global Session ( root-context) can be overriden by specific-servlet for customization.
I like the answer provided here also Understanding contexts in Spring MVC
A typical Spring MVC application will have two contexts: the root context and the servlet context.
The root context is loaded by the ContextLoaderListener. The ContextLoaderListener loads the ApplicationContext and sets it as an attribute in the ServletContext. This makes it available to other Servlet, Filter, and XxxListener instances.
The servlet context is another ApplicationContext loaded by the DispatcherServlet when its init() method is called. Since the init() method of a Servlet is called after the contextInitialized() method of a ServletContextListener is called, the DispatcherServlet has access to the root context set as an attribute in the ContextLoaderListener and can therefore use the beans declared there.
[...] creates the beans defined there, overriding the definitions of any
beans defined with the same name in the global scope.
A bean definition is, for example,
<bean id="someBean" class="com.company.SomeBean">
<property name="someProp" value="some value" />
</bean>
Spring creates a BeanDefinition object for this and all other <bean> declarations (or #Bean annotation methods). When the ApplicationContext is refreshed, Spring generates actual instances from these bean definitions.
What the above quote from the documentation is saying is that if you have a <bean> declaration with the same name or id in both the root context and the servlet context, the servlet context one will overwrite the root context one.
I am confused between ref and depends-on attribute in Spring.I read the spring doc but I am still confused.I wish to know the exact difference between the two and in which case which one shall be used.
From the official documentation: http://docs.spring.io/spring/docs/3.2.x/javadoc-api/org/springframework/context/annotation/DependsOn.html
Beans on which the current bean depends. Any beans specified are guaranteed to be created by the container before this bean. Used infrequently in cases where a bean does not explicitly depend on another through properties or constructor arguments, but rather depends on the side effects of another bean's initialisation.
Perhaps an example of a situation where depends-on is needed would help. I use Spring to load and wire my beans. Here is an example bean definition:
<bean id="myBean" class="my.package.Class">
<property name="destination" value="bean:otherBeanId?method=doSomething"/>
</bean>
<bean id="otherBeanId" class="my.package.OtherClass"/>
Notice that the property value is a string, which references otherBeanId. Because of the way this variable is resolved, Spring doesn't learn of the dependency, so it may destroy otherBeanId then myBean. This may leave myBean in a broken state for a little while.
I can use depends on to fix this problem as follows:
<bean id="myBean" class="my.package.Class" depends-on="otherBeanId">
<property name="destination" value="bean:otherBeanId?method=doSomething"/>
</bean>
There might be a situation where a bean might be a property in another bean i.e; the property bean is directly involved in the bean definition as a property in such case we refer the beans with ref attribute.
There might be a situation where in a bean instantiation is required for the other bean to be successfully created, the other bean is not a property of the bean under definition, in such case we make use of the depends-on attribute.
Lets say I have a situation like this:
<bean id="sample" class="ComlicatedClass" scope="prototype">
<property name="someProperty" value="${propertyValue}"/>
</bean>
I want to be able to create the bean programatically and provide value for propertyValue at runtime (pseudocode ahead):
appContext.getBean("sample", "propertyValue" => "value")
In a way, I want to create "bean template" rather than full defined bean. Is that possible in any way in spring?
EDIT:
The value for propertyValue is known at runtime! There is no way to define it as another bean.
why don't you just do
Sample sample = appContext.getBean("sample");
sample.setSomeProperty(appContext.getBean("someOtherBean"));
Have you looked at the Prototype scope?
The non-singleton, prototype scope of bean deployment results in the creation of a new bean instance every time a request for that specific bean is made. That is, the bean is injected into another bean or you request it through a getBean() method call on the container. As a rule, use the prototype scope for all stateful beans and the singleton scope for stateless beans.
There is also the #Scope annotation if you are using the Java based container configuration.
I need to chance spring bean property values on runtime. Currently I'm doing it this way
Object bean = context.getBean(beanName);
BeanWrapper wrapper = PropertyAccessorFactory.forBeanPropertyAccess(bean);
wrapper.setPropertyValue(propertyName, newValue);
But some beans are configured as abstract
<bean id="abstractFoo" abstract="true" class="com.Foo" />
<bean id="bar" class="com.Bar">
<constructor-arg><bean parent="abstractFoo" /></constructor-arg>
</bean>
and in that case context.getBean("abstractFoo") throws BeanIsAbstractException
This is really simplified example, but I hope you get the idea.
Any idea how to change property value of abstract bean (in this case 'abstractFoo')?
We're using spring 2.5.4
Edit
Changed a XML example to be more specific. abstractFoo is declared abstract because of security reasons.
Spring application context contains bean definitions, and Spring instantiates bean objects defined by these definitions.
Your current code obtains an object that was created from the named bean definition, and changes its property. However, abstract beans are never instantiated as objects, they exist only in the form of definitions which are inherited by definitions of concrete beans.
So, if you want to change properties of abstract beans, you need to change their definitions, that can be done using BeanFactoryPostProcessor. Note, however, that post-processors are applied during container startup, so if you want it to be actually "runtime", you this approach is not applicable.
Disclaimer: this is untested; off the top of my head. Not sure if it will work after the init phase.
You need to get in instance of a ConfigurableListableBeanFactory. Your appcontext probably is one, so you can probably cast it.
From there, get the bean definition and change the property.
ConfigurableListableBeanFactory clbf = (ConfigurableListableBeanFactory)context;
BeanDefinition fooDefinition = clbf.getBeanDefinition("abstractFoo");
MutablePropertyValues pv = fooDefinition.getPropertyValues();
pv.add(propertyName, newValue);
Maybe you need to re-register your beandefinition with the ConfigurableListableBeanFactory after that. I'm not 100% sure; you'll have to test that.
Keep in mind that if it works, it will only work for beans that are instantiated after the change.