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.
Related
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).
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);
}
I am trying to inject a prototype bean in a singleton bean such that every new call to a singleton bean method has a new instance of the prototype bean.
Consider a singleton bean as below:
#Component
public class SingletonBean {
#Autowired
private PrototypeBean prototypeBean;
public void doSomething() {
prototypeBean.setX(1);
prototypeBean.display();
}
}
I expect that every time the doSomething() method is called, a new PrototypeBean instance is utilized.
Below is the prototype bean:
#Component
#Scope(value="prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class PrototypeBean {
Integer x;
void setX(Integer x) {
this.x = x;
}
void display() {
System.out.println(x);
}
}
What seems to be happening is that spring is being overeager in handing over a new instance of PrototypeBean in the doSomething() method. That is, the 2 lines of code in the doSomething() method are creating a new instance of prototypeBean in each line.
And so in the 2nd line - prototypeBean.display() prints NULL.
What is missing in configuration for this injection?
From Spring documentation:
You do not need to use the <aop:scoped-proxy/> in conjunction with
beans that are scoped as singletons or prototypes. If you try to
create a scoped proxy for a singleton bean, the BeanCreationException
is raised.
It seems the documentation has changed a bit for version 3.2 documentation where you can find this sentence:
You do not need to use the <aop:scoped-proxy/> in conjunction with
beans that are scoped as singletons or prototypes.
It seems that its not expected you use a proxied prototype bean, as each time it is requested to the BeanFactory it will create a new instance of it.
In order to have a kind of factory for your prototype bean you could use an ObjectFactory as follows:
#Component
public class SingletonBean {
#Autowired
private ObjectFactory<PrototypeBean> prototypeFactory;
public void doSomething() {
PrototypeBean prototypeBean = prototypeFactory.getObject();
prototypeBean.setX(1);
prototypeBean.display();
}
}
and your prototype bean would be declared as follows:
#Component
#Scope(value="prototype")
public class PrototypeBean {
// ...
}
Singleton bean is created only once so the prototype bean which is injected also will be created once at the instantiation of singleton bean.The same instance of prototype bean will be used for every request.
If new instance of prototype bean will be created for each request at runtime ,the below method Injection can be used
Example
public class Singleton {
private Prototype prototype;
public Singleton(Prototype prototype) {
this.prototype = prototype;
}
public void doSomething() {
prototype.foo();
}
public void doSomethingElse() {
prototype.bar();
}
}
public abstract class Singleton {
protected abstract Prototype createPrototype();
public void doSomething() {
createPrototype().foo();
}
public void doSomethingElse() {
createPrototype().bar();
}
}
<bean id="prototype" class="ch.frankel.blog.Prototype" scope="prototype" />
<bean id="singleton" class="sample.MySingleton">
<lookup-method name="createPrototype" bean="prototype" />
</bean>
Right way to achieve it - use lookup method injection and everywhere where you used beans use lookup method invocation (detailed answer)
Since Spring 4.1 you can use annotation #Lookup
#Lookup
public PrototypeBean getPrototypeBean() {
return null;
}
Every time you will call method getPrototypeBean() - you will receive new prototype bean instance.
Don't worry about empty method realization: Spring will override it for you.
Read more in official documentation.
Spring wires up your beans in a pretty straight forward way. I'm working in a large commercial application, and I inserted the following code snippets to verify the load order.
1) All of your singleton bean class structures are initially loaded by Spring (as long as Spring is aware of them via annotations and/or xml). This only ever happens once. You can test this by logging or printing in a static block:
static {
log.info("#### classNameHere loaded"); //or println if no log setup
}
2) Spring creates all singleton instances that it is aware of (but not prototypes! Prototype instances WILL be created IF they are referenced inside a singleton bean - there class structures are of course loaded first). You can test this by adding this method to each class:
#PostConstruct
public void methodHitAfterClassInstantiation() {
LOGGER.info("#### instance of classNameHere");
}
So in your example, the class structures of SingletonBean is loaded when Spring starts up. A new instance of SingletonBean is created.
And because PrototypeBean is Autowired inside of SingletonBean, its class structure is loaded and an instance of it is created. Now, if there was another bean, say AnotherSingletonBean, with an Autowired PrototypeBean inside
of it, then a DIFFERENT instance of PrototypeBean would be created (no need to load the class structure again). So there is only ever 1 SingletonBean, and inside of it is a PrototypeBean, which
will always point to the same bean. Because of this, singletons should always be stateless, as all of your other beans that use a singleton will be pointing at the
same object. But you CAN maintain state in a prototype bean, because wherever you create a new reference, you will be pointing at another bean object.
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-factory-scopes-prototype
In Spring, is it possible to override a singleton bean definition with a scoped proxy?
Namely, if I have some
#Configuration
public class MyConfiguration
{
#Bean
public Foo foo()
{
return new Foo();
}
}
I want to create a test configuration but with a custom scope for "Foo":
#Configuration
public class MyTestConfiguration extends MyConfiguration
{
#Override
#Scope(value="myTestScope", proxyMode=ScopedProxy.TARGET_CLASS)
public Foo foo()
{
return new Foo();
}
}
However, this approach doesn't work! The constructed Foo is still a singleton! Unfortunately, adding #Primary and adding #Bean annotations to the test configuration doesn't help either. Is there any way to override a singleton with a scoped proxy?
The valid scopes values are :
singleton – Return a single bean instance per Spring IoC container
prototype – Return a new bean instance each time when requested
request – Return a single bean instance per HTTP request. session –
Return a single bean instance per HTTP session. globalSession –
Return a single bean instance per global HTTP session.
There is a #Bean annotation in Spring 3.0. It allows to define a Spring bean directly in a Java code. While browsing Spring reference I found two different ways of using this annotation - inside class annotated with #Configuration and inside class which doesn't have this annotation.
This section contains following piece of code:
#Component
public class FactoryMethodComponent {
#Bean #Qualifier("public")
public TestBean publicInstance() {
return new TestBean("publicInstance");
}
// omitted irrelevant method
}
And here we could see a very similar piece of code, but now #Configuration is in the place:
#Configuration
public class AppConfig {
#Bean
public MyService myService() {
return new MyServiceImpl();
}
}
Former section of reference contains following explaination:
The #Bean methods in a Spring component are processed differently than their counterparts inside a Spring #Configuration class. The difference is that #Component classes are not enhanced with CGLIB to intercept the invocation of methods and fields. CGLIB proxying is the means by which invoking methods or fields within #Configuration classes #Bean methods create bean metadata references to collaborating objects. Methods are not invoked with normal Java semantics. In contrast, calling a method or field within a #Component classes #Bean method has standard Java semantics.
But CGLIB is a kind of internal stuff which application developer shouldn't be aware of (in a ideal world, of course). As I understand in both cases Spring invokes method annotated with #Bean to create Spring bean, in both cases these instances are injected to collaborators.
So my question is what is the difference for me as an application developer between this two cases?
The difference is that with #Configuration you can call one #Bean method from another and get a fully initialized instance, as follows:
public class Foo {
#Value("Hello, world!")
public String value;
}
#Configuration
public class Config {
#Bean
public Foo createFoo() {
Foo foo = new Foo();
System.out.println(foo.value); // Prints null - foo not initialized yet
return foo;
}
#Bean
public Bar createBar() {
Foo foo = createFoo();
System.out.println(foo.value); // Prints Hello, world! - foo have been initialized by the interceptor
return new Bar(foo);
}
}
#Bean [instance method] inside #Component - One method with #Bean instance call other method #Bean instance , then it would be simple java semantics call i.e. Object won't returned by Spring container , It would be normal return from java instance factory method,because Component class don't extends CGLIB.
#Bean [instance method] inside #Configuration - In this case , spring container would be returning reference to exisiting object. It won't be normal java sematic call.
#Bean on static method inside Configuration & Component Class - In this case , #Bean method would never be intercepted by the container neither in Configuration class nor in Component Sterotype class.