Getting Spring beans by method invocation vs new operator - java

I am confused about this little topic. Somewhere I read that if a class is annotated with #Component, it is spring managed bean and whenever it is required, spring will provide it. I am confusing it with scope of a bean. Let me explain:
Let's say a class
#Component
public class Example{ }
If I instantiate this class in other class using new Example(), would container always provide me the same Example object all the time? Or would it return me new object every time?
Here comes the confusing part:
If in the same class I have two beans like this:
#Component
public class Example {
#Bean DataSource sqlDataSource() {
// some logic
}
#Bean #Scope("prototype") SomeObject getSomeObject() {
return new SomeObject(sqlDataSource()); //**
}
}
What will happen in this case? sqlDataSource() method invocation would return the same object again and again every time SomeObject bean is requested, or new instance of DataSource will be returned every time SomeObject is requested?

#Bean is a method-level annotation that indicates Spring to create a bean when that method is invoked. It means to have the same functionality thatn tag in XML config.
This annotation must be used inside of a #Configuration annotated class, otherwise if you invoke the method from another method it will be a normal java new operation, not spring's. See this post --> #Bean inside class with #Configuration and witout it
Bearing this in mind new SomeObject(sqlDataSource()); would be equal to new SomeObject(new SqlDataSource());
if you annotate Example with #Configuration what will happen is that you'll get always a new SomeObject instance with the same sqlDataSource object, this means that Spring will take care of creating ONLY ONE sqlDataSource because it is singleton.

#Bean DataSource sqlDataSource() {
// some logic
}
This defines a singleton instance of DataSource. So everytime you request an instance of SomeObject a new SomeObject will be created (while it is defined in the prototype scope) but all of them will share the same DataSource object (since it's a singleton bean).

Related

Proxy pattern used by spring

I am learning spring :)
I have following doubts,
Does spring creates proxy object for every bean even if I have not used annotations for example #Transactional which I think need proxy.
I read following in spring documentation
Note that calls to static #Bean methods will never get intercepted by the container, not even within #Configuration classes (see above). This is due to technical limitations: CGLIB subclassing can only override non-static methods. As a consequence, a direct call to another #Bean method will have standard Java semantics, resulting in an independent instance being returned straight from the factory method itself.
a. Spring does not return proxy object in following example because of static method which is cannot override. So it will return original object here. Am I right?
#Configuration
public class Config {
#Bean
public static Student student() {
return new Student();
}
}
b. What is meaning of "Note that calls to static #Bean methods will never get intercepted by the container, not even within #Configuration classes"
a. Yes, you are correct. You will get the original object.
b. student() method is inside the class Config which is annotated with #Configuration annotation. All the methods which are annotated with #Bean inside #Configuration class are intercepted by spring by creating proxies. So as your method is static and though it is inside Config class, it will not be intercepted by Spring and no proxies will be created.

Spring boot bean into bean injection methodology

Can anyone tell me if there is a difference (in terms of spring bean injection and respecting singleton conditions or any other spring boot magic) in these two spring boot application classes?
#Bean
#Scope("singleton")
public UserService userService(Foo foo){
return new UserService(foo);
}
#Bean
#Scope("singleton")
public Foo foo(){
return new Foo();
}
AND calling not declaring Foo as a method parameter on userService() but rather injecting it via a direct method call to foo()
#Bean
#Scope("singleton")
public UserService userService(){
return new UserService(foo());
}
#Bean
#Scope("singleton")
public Foo foo(){
return new Foo();
}
No, there is no difference. One might think, you would get a new bean instance everytime you call foo() in that configuration class, but the way Spring works in that case is, it creates a proxy for that configuration class which intercepts all method calls. The proxy then checks, if there is already a bean of type Foo, if so it returns the existing instance, otherwise the method call is delegated to the implementation and a new bean is created.
Code style wise, however, i think in your first example the dependency to the Foo bean is more clearly marked than in the second example.

Why do I not need #Autowired on #Bean methods in a Spring configuration class?

Why does this work:
#Configuration
public class MyConfig {
#Bean
public A getA() {
return new A();
}
#Bean // <-- Shouldn't I need #Autowired here?
public B getB(A a) {
return new B(a);
}
}
Thanks!
#Autowire lets you inject beans from context to "outside world" where outside world is your application.
Since with #Configuration classes you are within "context world ", there is no need to explicitly autowire (lookup bean from context).
Think of analogy like when accessing method from a given instance. While you are within the instance scope there is no need to write this to access instance method, but outside world would have to use instance reference.
Edit
When you write #Configuration class, you are specifying meta data for beans which will be created by IOC.
#Autowire annotation on the other hand lets you inject initialized beans, not meta-data, in application. So, there is no need for explicit injection because you are not working with Beans when inside Configuration class.
Hi Jan your question is marked as answered over 4 years ago but I've found a better source:
https://www.logicbig.com/tutorials/spring-framework/spring-core/javaconfig-methods-inter-dependency.html
here's another article with the same idea:
https://dzone.com/articles/spring-configuration-and, it also states that such usage is not well documented which I found true. (?)
so basically if beanA's initialization depends on beanB, spring will wire them without explicit #Autowired annotation as long as you declare these two beans in the application context (i.e. #Configuartion class).
A class with #Configuration annotation is where you're defining your beans for the context. But a spring bean should define its own dependencies. Four your case B class should be defining it's own dependencies in class definition. For example if your B class depends on your A class than it should be like below:
public class B
{
#Autowired
A aInstance;
public A getA()
{
return aInstance;
}
public void setA(A a)
{
this.aInstance = a;
}
}
In above case while spring is building its context it looks for the bean which's type is A which is also defined as a Bean at your configuration class and Autowires it to B at runtime so that B can use it when required.

Why in Spring I am not allowed to annotate a final class with #Configuration?

I am studying for the Spring Core certification and I have some doubts related to the answer of this question founded on the study material stuff.
Why are you not allowed to annotate a final class with #Configuration
My reasoning is the following one for substantiate this assertion:
Consider the following configuration class:
#Bean
public AccountRepository accountRepository() {
return new JdbcAccountRepository();
}
#Bean
public TransferService transferService() {
TransferServiceImpl service = new TransferServiceImpl();
service.setAccountRepository(accountRepository());
return service;
}
#Bean
public AccountService accountService() {
return new AccountServiceImpl(accountRepository());
}
At first look this situation could appear strange because the first method (accountRepository()) instantiates an JdbcAccountRepository object as a bean having id=AccountRepository that, following the Spring default behavior, is a singleton
The second and the third method call twice more time the accountRepository() method that should instantiate twice more JdbcAccountRepository objects and this is not possibile because it is singleton !!!
So, to solve this situation Spring use the Inheritance-based Proxies strategy that expect to create a child class of my configuration class (the one annoted by #Configuration) and it is does:
For each bean, an instance is cached in the child class
Child class only calls super at first instantiation
So the child class is the entry point because the following behavior is implemented by this child class:
public class AppConfig$$EnhancerByCGLIB$ extends AppConfig {
public AccountRepository accountRepository() {
// if bean is in the applicationContext
// return bean
// else call super.accountRepository() and store bean in context
}
public TransferService transferService() {
// if bean is in the applicationContext, return bean
// else call super.transferService() and store bean in context
}
.....................................................
.....................................................
.....................................................
}
So if I annotate a configuration class with final Spring can't have this behavior because in Java a final class cannot be subclassed
Is it correct?
Using the same reasoning can I also assert that in Spring I can't have a final method annoted with #Bean annotation?
Because, as shown in the previous example, I have that when at startup time is created the child class (the proxy) of my configuration class happens that for each bean, an instance is cached in the child class and if it is final it is not possible (but I am absolutly not sure about this assertion)
Am I missing something? Can you give me the exact explaination?
Tnx
Spring creates dynamic proxies for classes annotated with #Configuration classes. Spring uses CGLIB to extend your class to create proxy. Hence, configuration classes cannot be final.
Regarding accountRepository() being invoked twice:
If you invoke accountRepository() method to create an instance, it is no more a Spring managed bean. Spring will not have any idea of the instances created in this manner. Hence, you will end up with multiple instances of JdbcAccountRepository
You can preserve the singleton behavior if you configure as below:
#Bean
public TransferService transferService(JdbcAccountRepository jdbcAcctRepo) {
TransferServiceImpl service = new TransferServiceImpl();
service.setAccountRepository(jdbcAcctRepo);
return service;
}
#Bean
public AccountService accountService(JdbcAccountRepository jdbcAcctRepo) {
return new AccountServiceImpl(jdbcAcctRepo);
}

Autowire of prototype bean into prototype bean?

I'm working with some existing code and it is doing things I haven't seen before. I've dealt with autowiring prototype beans into singletons using method injection or getting the bean from the context using getBean(). What I am seeing in this code I am working on is a bean that is a prototype and retrieved using getBean(), and it has autowired dependencies. Most of these are singleton beans, which makes sense. But there is an autowire of another prototype bean, and from what I see, it does seem like it is getting a new bean. My question is when you autowire a prototype into a prototype, will that give you a new instance? Since the autowire request is not at startup but rather when this bean is created, does it go and create a new instance? This goes against what I thought about autowire and prototype beans and I wanted to hear an answer from out in the wild. Thanks for any insight. I'm trying to minimize my refactoring of this code as it is a bit spaghetti-ish.
example:
#Scope("prototype")
public class MyPrototypeClass {
#Autowired
private ReallyGoodSingletonService svc;
#Autowired
private APrototypeBean bean;
public void doSomething() {
bean.doAThing();
}
}
#Scope("prototype)
public class APrototypeBean {
private int stuffgoeshere;
public void doAThing() {
}
}
So when doSomething() in MyPrototypeClass is called, is that "bean" a singleton or a new one for each instance of MyPrototypeClass?
In your example, the APrototypeBean bean will be set to a brand new bean which will live through until the instance of MyPrototypeClass that you created is destroyed.
If you create a second instance of MyPrototypeClass then that second instance will receive its own APrototypeBean. With your current configuration, every time you call doSomething(), the method will be invoked on an instance of APrototypeBean that is unique for that MyPrototypeClass object.
Your understanding of #Autowired or autowiring in general is flawed. Autowiring occurs when an instance of the bean is created and not at startup.
If you would have a singleton bean that is lazy and that bean isn't directly used nothing would happen as soon as you would retrieve the bean using for instance getBean on the application context an instance would be created, dependencies get wired, BeanPostProcessors get applied etc.
This is the same for each and every type of bean it will be processed as soon as it is created not before that.
Now to answer your question a prototype bean is a prototype bean so yes you will receive fresh instances with each call to getBean.
Adding more explanation to #Mark Laren's answer.
As explained in Spring 4.1.6 docs
In most application scenarios, most beans in the container are
singletons. When a singleton bean needs to collaborate with another
singleton bean, or a non-singleton bean needs to collaborate with
another non-singleton bean, you typically handle the dependency by
defining one bean as a property of the other. A problem arises when
the bean lifecycles are different. Suppose singleton bean A needs to
use non-singleton (prototype) bean B, perhaps on each method
invocation on A. The container only creates the singleton bean A once,
and thus only gets one opportunity to set the properties. The
container cannot provide bean A with a new instance of bean B every
time one is needed.
Below approach will solve this problem, but this is not desirable because this code couples business code with Spring framework and violating IOC pattern. The following is an example of this approach:
// a class that uses a stateful Command-style class to perform some processing
package fiona.apple;
// Spring-API imports
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class CommandManager implements ApplicationContextAware {
private ApplicationContext applicationContext;
public Object process(Map commandState) {
// grab a new instance of the appropriate Command
Command command = createCommand();
// set the state on the (hopefully brand new) Command instance
command.setState(commandState);
return command.execute();
}
protected Command createCommand() {
// notice the Spring API dependency!
return this.applicationContext.getBean("command", Command.class);
}
public void setApplicationContext(
ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
So, there are 2 desirable ways to solve this problem.
1. Using Spring's method injection
As name suggests, Spring will implement & inject our abstract method by using #Lookup annotation from Spring 4 or tag if you use xml version. Refer this DZone article.
By using #Lookup.
from Java Doc...
An annotation that indicates 'lookup' methods, to be overridden by the
container to redirect them back to the BeanFactory for a getBean call.
This is essentially an annotation-based version of the XML
lookup-method attribute, resulting in the same runtime arrangement.
Since:
4.1
#Component
public class MyClass1 {
doSomething() {
myClass2();
}
//I want this method to return MyClass2 prototype
#Lookup
public MyClass2 myClass2(){
return null; // No need to declare this method as "abstract" method as
//we were doing with earlier versions of Spring & <lookup-method> xml version.
//Spring will treat this method as abstract method and spring itself will provide implementation for this method dynamically.
}
}
The above example will create new myClass2 instance each time.
2. Using Provider from Java EE (Dependency Injection for Java (JSR 330)).
#Scope(BeanDefinition.SCOPE_PROTOTYPE)
#Component
public static class SomeRequest {}
#Service
public static class SomeService {
#Autowired
javax.inject.Provider<SomeRequest> someRequestProvider;
SomeRequest doSomething() {
return someRequestProvider.get();
}
}
The above example will create new SomeRequest instance each time.

Categories

Resources