I was in the impression that whenever a class implements an interface then JDK based proxies are created.
I have a bean which implements an interface with prototype scope which is injected in a bean with singleton scope. I tried using proxyMode = ScopedProxyMode.INTERFACES JDK proxy was created which is right, but when I tired proxyMode = ScopedProxyMode.TARGET_CLASS then CGLIB based proxy is created even though my bean implements an interface.
what happens when
proxyMode = ScopedProxyMode.TARGET_CLASS
and
proxyMode = ScopedProxyMode.INTERFACES
what is the difference between them? when to use which one?
One more question I have is what is the correct way to inject prototype bean into singleton bean?
In general, no proxy is needed in a scenario where a prototype scoped bean is injected into a singleton scoped bean.
The reference documentation states:
You do not need to use the <aop:scoped-proxy/> in conjunction with beans that are scoped as singletons or prototypes.
What happens without a proxy?
When the Spring context is being created and the singleton bean instantiated, a new instance of the prototype bean is created and injected into the singleton. Every invocation of our singleton now uses the same instance of the prototype.
Why would you need the proxy?
Maybe you want to alter the default behavior and create a new prototype bean instance for every invocation of the singleton bean. With the proxy, the singleton bean will keep the same proxy instance for all invocations. With every invocation, the proxy will get a new prototype bean instance from the Spring context.
The proxy modes
The proxy modes are self-descriptive. See ScopeProxyMode Javadoc:
ScopeProxyMode.INTERFACES - Create a JDK dynamic proxy implementing all interfaces exposed by the class of the target object.
ScopeProxyMode.TARGET_CLASS - Create a class-based proxy (uses CGLIB).
Does the singleton bean depend on an interface implemented by the prototype bean? Use ScopeProxyMode.INTERFACES. Otherwise, use ScopeProxyMode.TARGET_CLASS.
A method injection would be an alternate approach to get the same behavior as with the proxy.
Related
I have been trying to understand spring beans. As per my understanding, by default all beans are singleton and a singleton bean with lazy-init property set to true is created when it is first requested and singleton bean with lazy-init property set to false is created when the application context is created.
So, in an application, when a user request comes in ( where each request is a separate thread), do all these threads share the same singleton beans when requested within the program/class?
Yes, if the bean is created with default scope, the bean is shared across threads. However, another scope can be used to achieve the behaviour you mentioned.
See: https://docs.spring.io/spring-framework/docs/3.0.0.M3/reference/html/ch04s04.html?
Yes, by default (scope == 'singleton'), all threads will share the same singleton bean. There are two other bean scopes, session and request, that may be what you're looking for. The request scope creates a bean instance for a single HTTP request while session scope maintains a unique bean for each HTTP Session.
For a list and description of all of the Spring bean scopes, check out: Spring bean scopes
The best way to understand this is to understand how #Autowired annotation works.
Or in other words to understand "Spring Dependency Injection".
You said, "
by default all beans are singleton
We use #Autowired when injecting one layer into another between two layers.
If exemplify: Suppose, I want to inject UserService UserController. UserService is a Singleton bean. Creates an instance from UserService and Stores its cache. When we want to inject this service with #Autowired annotation. This annotation brings the UserService stored in the cache.
In this way, Even if we do this inject operation in many classes.#Autowired inject an instance of UserService with singleton bean instead of dealing with one UserService at each time. It saves us a big burden.
This is the fundamental working logic of Spring Singleton Bean.
Also, Spring Ioc Container manages this whole process.
Class Student Depends on class Result
<bean id = "result" lazy-init = "false">
</bean>
<bean id = "student" lazy-init = "true">
</bean>
Result: result bean will be loaded at container start-up and student will be loaded when we call getBean method.
<bean id = "result" lazy-init = "false" scope = "prototype">
</bean>
<bean id = "student" lazy-init = "true" scope = "Singleton">
</bean>
Result: No bean will be loaded at container start-up.
Question: Why scope is affecting class load; what does scope have to do with class load time?
According to documentation
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.
Since you didn't yet call getBean or inject it to another bean, this bean is not been created.
By the way, even when you declared your singletone bean as lazy-init="true", it will be created, if you'll inject it (for example with #Autowired annotation) to other non-lazy bean.
A bean of scope singleton is a bean that is created once per application context. A bean of scope prototype is a bean that is instantiated every time.
In other words if your have two classes that autowire a singleton scoped bean, all instances of those two classes will reference the same single instance of the bean. Doing the same with autowiring a prototype scoped bean will create a new instance for each instance that is autowired.
The property for lazy-init defines when the bean is instantiated: As a prototype scoped bean is instantiated each time there is no difference if the property is set to true or false, because the bean is instanciated when it is used (either by being autowired or by programmatic retrieval from the context). For a singleton scoped bean however it does make a difference:
If lazy-init is set to false (which is the default), the bean is instantiated on startup.
If the property is set to true, the bean is instantiated on the first use (through autowiring or programmatic retrieval from the context).
Defining a lazy load singleton bean may come in handy in cases where the bean may be costly to create and may only be used in special cases, the the application may actually run without ever calling any method on that bean.
Take a look at the Spring IoC container documentation, which goes into great detail.
I would like to put the theory in a simple manner which will help you understand better,
Only Singleton beans are eager loaded | prototype beans are lazily loaded(every req or indirect references)
If singleton bean is defined as lazy-init=true (by-default its false) then bean will be instantiated on first usage(using getBean or any indirect reference)
But for prototype bean lazy-init does not make any diff if making lazy-init=true or false as it will be lazily loaded always
You can try using #PostConstruct to play around different combinations in spring bean injections to know when beans are getting instantiated.
Is it possible to inject new instances of prototype scoped beans to Controller's method arguments at runtime using annotations in Spring? So whenever the method is called, Spring would inject the qualifying bean as its argument, familiarly as it injects #ModelAttribute. As far as I know, #Autowired fields are injected only once when context is created. Obtaining the bean from context's factory method isn't an option, as that would expose framework to its component, thus violating the hollywood principle.
I have almost completed reading Spring in Action book and have been reading Spring Reference a lot, but haven't found any info regarding this question.
You have a couple of options.
Define a prototype bean and inject that wrapped in an ObjectFactory
#Autowired
private ObjectFactory<PrototypeBean> factory;
You can then retrieve it in your handler method. For example
#RequestMapping("/path")
public String handlerMethod() {
PrototypeBean instance = factory.getObject();
instance.someMethod();
return "view";
}
Every time you call factory.getObject(), you'll get a new instance.
As for doing this directly, no, Spring MVC does not have a built-in feature for having beans injected while invoking handler methods, with #Autowired or otherwise.
However, the HandlerMethodArgumentResolver API allows you to define an implementation for any type of parameter you want. You can define a new annotation and use it to annotate the appropriate handler method parameter(s). The implementation would look for the annotation and resolve an instance from an injected ApplicationContext. You could do this by name, by type, however you want.
I have a session scoped bean which is injected into a singleton bean using a proxy.
From the singleton bean I need to call a certain init-method of the session scoped bean, which needs the singleton bean as parameter.
Furthermore I can not change the source of the session scoped bean.
To elaborate the case:
The singleton bean is a Service and the session scoped bean is a Vaadin4Spring eventbus, for which I need to call the method eventBus.subscribe(this).
There seems to be no way to check, if I am already subscribed and I must not call subscribe twice on a certain eventBus instance.
Is there a way to tell Spring to call eventBus.subscribe(this) when the proxy links to an eventBus instance for the first time?
Can't you just go the other way round, inject the service into your eventbus, and call this.subscribe(serviceBean) in a #PostConstruct annotated method in the eventbus? Then it would only be called once when the eventbus is constructed.
You could add #Lazy to the Singleton. You do not need the Proxy.
I have created stateless session bean in Java. Now I want to invoke a method of another stateless session bean. Some things are missing in my code. Usual way of invoking method does not fit here. Being invoked method at another stateless session bean retrieves data from the Internet.
Likewise, how to invoke a method from #Stateless bean of a simple Java class. I build a REST web service with Java and somehow I can't invoke methods being at simple Java class from #Stateless beans.
Cheers
Just inject it with #EJB
#Stateless
public class StatelessBean1 {
#EJB
private StatelessBean2 bean;
}
There's nothing special about invoking methods on a stateless session bean. You use the exact same syntax as with every other kind of bean.
As Bozho indicated, the only thing special about EJBs is that you can't construct an instance using the new operator. You need to inject an instance or alternatively do a JNDI lookup. After that, the normal Java rules apply.
It really shouldn't need to be explained but to be sure, calling a method on a stateless session bean called 'bean':
bean.someMethod(someArgument);