I have a abstract bean "home", a child bean "homechild" and a bean "my" to be injected in the parent. I tried to autowire the "my" bean in the parent. But it does not happen. Is this because autowiring in a abstract bean is not possible?
<bean id="home" class="my.test.own.spring_book_ch3.HomeImpl"
autowire="byType" abstract="true"/>
<bean id="homechld" parent="home"/>
<bean id="my" class="my.test.own.spring_book_ch3.MyImpl"/>
When I explicit inject, it works.
<bean id="home" class="my.test.own.spring_book_ch3.HomeImpl"
autowire="byType" abstract="true">
<property name="my" ref="my"/>
</bean>
Short answer is No, abstract parent bean cannot use autowire for injection.
From spring's reference document the child bean dictates the autowire mode
A child bean definition inherits scope, constructor argument values, property values, and method overrides from the parent, with the option to add new values. Any scope, initialization method, destroy method, and/or static factory method settings that you specify will override the corresponding parent settings.
The remaining settings are always taken from the child definition: depends on, autowire mode, dependency check, singleton, lazy init.
Also the container ignores the abstract beans from instantiation thus no question of autowiring any dependencies.
ApplicationContext pre-instantiates all singletons by default. Therefore, it is important (at least for singleton beans) that if you have a (parent) bean definition which you intend to use only as a template, and this definition specifies a class, you must make sure to set the abstract attribute to true, otherwise the application context will actually (attempt to) pre-instantiate the abstract bean.
Related
We register some beans with custom bean definition, in a BeanPostProcessor we need to access the bean definition
public Object postProcessBeforeInitialization(Object bean, String beanName)
I can make it ApplicationContextAware and then do:
((ConfigurableApplicationContext)applicationContext).getBeanFactory().getBeanDefinition(beanName)
but is it assured that the applicationContext is always ConfigurableApplicationContext?
Is there another way to access the bean definition from a BeanPostProcessor?
If you need to access BeanDefinition instances, you should use BeanFactoryPostProcessor instead of BeanPostProcessor.
BeanFactoryPostProcessor
Allows for custom modification of an application context's bean
definitions, adapting the bean property values of the context's
underlying bean factory. A BeanFactoryPostProcessor may interact with and modify bean definitions, but never bean instances.
BeanPostProcessor
Factory hook that allows for custom modification of new bean
instances, e.g. checking for marker interfaces or wrapping them with
proxies.
I have declared following list using spring util namespace in my spring configuration file:
<util:list id="childList">
<ref bean="child1"/>
<ref bean="child2"/>
<ref bean="child3"/>
</util:list>
where all reference bean are marked with #Componant annotation and their respective beans are creating. But whenever I am trying to Autowired any beans property like:
#Component
public class ListTest{
#Autowired
#Qualifier("childList")
private List<IParent> list;
public List<IParent> getList() {
return list;
}
}
Gives exception as: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'listTest': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private java.util.List com.spring3.componentScanFilterTest.ListTest.list; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.spring3.componentScanFilterTest.IParent] found for dependency [collection of com.spring3.componentScanFilterTest.IParent]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true), #org.springframework.beans.factory.annotation.Qualifier(value=childList)}
But instead of #Autowired and #Qualifier if I use as:
#Resource(name="childList")
It works. Why? As per my understanding #Autowired is used to autowire the property matching by type and #Qualifier is used to select any one bean from multiple ambiguous beans.
Please explain.
Spring docs says.
As a specific consequence of this semantic difference, beans that are themselves defined as a collection or map type cannot injected through #Autowired, because type matching is not properly applicable to them. Use #Resource for such beans, referring to the specific collection or map bean by unique name.
Hope this clear your doubt.
Type matching is not properly applicable to beans which defined as collection.
If you intend to express annotation-driven injection by name, do not primarily use #Autowired - even if is technically capable of referring to a bean name through #Qualifier values. Instead, prefer the JSR-250 #Resource annotation which is semantically defined to identify a specific target component by its unique name, with the declared type being irrelevant for the matching process.
As a specific consequence of this semantic difference, beans which are themselves defined as a collection or map type cannot be injected via #Autowired since type matching is not properly applicable to them. Use #Resource for such beans, referring to the specific collection/map bean by unique name.
Here:
http://docs.spring.io/spring/docs/2.5.x/reference/beans.html#beans-autowired-annotation-qualifiers
You are trying to get list of all beans of type Parent that have the qualifier "childList".
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 there any lifecycle method of bean which gets called after bean is created .
I dont want to use init or destroy callback method of bean
If you put #PostConstruct annotation on any public method of your bean class, Spring will call it after the bean is created and all its dependencies are injected.
Yes! there is
<bean id="personDet" class="com.beans.PersonDet" init-method="yourInitMyBean()">
There is an attribute for each bean definition i.e init-method
The method yourInitMyBean() in PersonDet class will load first time when bean is created and will never call again
Similarly there is destroy-method attribute for bean defination
<bean id="personDet" class="com.beans.PersonDet" destroy-method="destroyBean()">
The method destroyBean() will be called only when you trying to shutdown your application or when the time your closing your beanFactory , ApplicationContext call close() method.
You can put both the attribute in-order test..
Hope it helps.
I want to use #AutoWired to inject a non-managed bean configured with #Component into a managed bean. I'm pretty sure I have the configuration right, but for some reason I keep getting the exception:
No unique bean of type [foo.Baz] is defined: Unsatisfied dependency of type [class foo.Baz]: expected at least 1 matching bean
Based on the error, I'm guessing it's not able to find the Baz class, but I'm not sure why. It's my understanding that the context:spring-configured element in the XML config was supposed to allow me to do this. I also made sure to include the appropriate jar files (spring-weaving.jar and aspectjweaver.jar).
Here's a simple example of my set up.
My XML config:
<beans ...>
...
<context:annotation-config/>
<context:spring-configured/>
<context:component-scan base-package="foo"/>
<bean id="bar" class="foo.Bar"/>
...
</beans>
I have one managed bean:
package foo;
public class Bar {
#Autowired
private Baz baz;
public void setBaz(Baz baz) {
this.baz = baz;
}
...
}
And one unmanaged bean:
package foo;
#Component
public class Baz {
...
}
Is there something I'm missing?
EDIT: The log lists the beans its instantiating, and foo.Baz isn't one of them. I don't know why it's not picking up the #Component annotated class.
Because Bar is configured with xml, it can only be configured with xml. i.e. you can't mix them. So that "#Autowired" annotation on Baz is not getting picked up (none of the annotations would be). It is only when you add the spring annotation at class level that spring will listen to any of the other annotations.
What you'll need to do is in the xml configure the bean to be autowired by type, add a setter for that type and you'll achieve the desired behaviour.
<bean id="bar" class="foo.Bar" autowire="byType"/>
One more thing, when you annotate a bean with #Component it is a spring managed bean. Just because it is not created with xml does not mean it is unmanaged. An unmanaged bean is one you don't get from spring.
Bar and Baz are both spring managed. It is the mechanism you've chosen to define them that differs.
The previous response is not correct, in one aspect. You can autowire beans that are otherwise configured with xml.
From section 3.4.5 in http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html:
When using XML-based configuration metadata[2], you specify autowire mode for a bean definition with the autowire attribute of the element. The autowiring functionality has five modes. You specify autowiring per bean and thus can choose which ones to autowire.
You can autowire by name, type and constructor. There is a crude example of this here: http://www.java2s.com/Code/Java/Spring/AutoWiring.htm
The error is due to the sequence of beans defined in your XML config file.
As on your XML file, bean for bar is created first and then their dependent beans due to which #Autowired is not able to find baz.
You must first declare bean for baz and then for bar.