Reading some source code and I stumbled upon this spring bean
#Service
public class ValidationService {...}
Which is instantiated manually using the new() operator in many places
ex:
var validationService=new ValidationService();
Now I am thinking to refactor all of these instantiations and replace it with proper spring injection.
It made me think about what would happen if we instantiated a bean using the new() operator. Will it create a new instance of the bean or will it just retrieve the spring managed instance ?
When the object is instantiated manually, it acts like a normal Java object.
Spring is not involved, so all the "spring features" (Inversion of control, dependency injection, etc..) not available.
Related
How does constructor method dependency injection work if I'm not even initializing the class anywhere or passing in arguments. Does Spring take care of this somewhere for me? Would really like to know more about this, if anyone wouldn't mind sharing/teaching me. How does this work on the heap? Would there be a reference to the class being constructed and the dependency so I would have two instances of different objects or just one? I found this answer How does constructor dependency injection work?, but it doesn't really answer my question in great detail.
Example:
#Controller
#RequestMapping
public class SampleController{
private final SomeRepository someRepository;
pulbic SampleController(SomeRepository someRepository) throws Exception{
// will someRepository ever be null?
if(someRepository == null)
throw new Exception("I told you it wouldn't work!");
this.someRepository = someRepository;
}
Answering your question: yes. Spring manages all the Beans on your behalf. You can declare a Bean in multiple ways:
XML (the old way);
Using #Bean (but in this case you would actually instantiate the Bean);
Using #Component, #Service, #Repository or #Controller (the later 3 are basically specializations of the first).
In your case, you have annotated SampleController with #Controller, so now Spring knows that it will need to provide this Bean for you by managing it in the Spring IoC container. However, so that Spring can create the Bean it will also understand that it needs another Bean to be available, in your case SomeRepository. If such a Bean already exists in Spring IoC Container then Spring provides it to your SampleController constructor. For this to work, SomeRepository must also be a Spring-managed Bean, and thus defined by one of the previous three ways.
It is worth mentioning that if for example you would have multiple SomeRepository Beans in your application (imagine an interface having multiple implementations, being each one a different Bean), you would need to "tell" Spring which one you want to be used in SampleController, otherwise you would get an error. There are multiple ways to do this:
Using #Qualifier annotations;
Using #Primary on one of the implementations to mark it as the "default" in case you don't explicitly "say" which one you want.
You can check examples in https://www.baeldung.com/spring-qualifier-annotation.
This is a very high-level description, but you can find some good articles online about this or even check the reference documentation.
I have a use case where I am using a utility class (class which contains methods that are all static and the constructor is also private). Therefore, I am not creating the object of the class, I am just accessing the methods with the class name. So, in the utility class I want to access the application.properties. But neither #Value nor autowiring Environment works. It always returns null.
Is there a way to access fields in application.properties in a utility class? I searched for it a lot, but I didn’t find any references.
That's the problem with static classes and fields. Their creation is not in the hands of the Spring or any other dependency injection framework. Thus, Dependency injection frameworks can't inject any value into it.
You can access beanManager and read the value or post initialize your values when spring boot is initialized. Still, your value is null while the Spring boot initialization process is in progress.
Better yet define a Singleton bean using Spring #Scope("singleton").
Change your class to a normal one and let its lifecycle and creation be managed by Spring, you will make it easier to test cuz testing static classes is not always easy.
I'm studying spring beans and came across #Lookup, it says:
If we happen to decide to have a prototype Spring bean, then we are
almost immediately faced with the problem of how will our singleton
Spring beans access these prototype Spring beans?
hmm, I don't get it, because when I studied scope=prototype it says:
4.4.2 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
so it seems i misinterpreted the words:
a request for that specific bean is made
actually programming in spring framework every line of the code is inside of some bean (i.e. #controller, #Service, etc), isn't it?
And almost all of them are singletons, isn't it?
So if I need prototype I just make scope=prototype and almost everytime it's injected to another bean (i.e. #controller, #Service, etc) isn't it?
So please give a real world scenarios, 1) when one should use #Lookup and 2) when it's not needed
Ok for the 1) the scenario:
#Component
#Scope("prototype")
public class SchoolNotification {
// ... prototype-scoped state
}
#Component
public class StudentServices {
// ... member variables, etc.
#Lookup
public SchoolNotification getNotification() {
return null;
}
// ... getters and setters
}
Please, show me scenario for the 2) case, and explain please the difference
Thank u
The implicit Bean scope in Spring is Singleton.
That means for a JVM instance, only a single instance of a Bean exists in memory (theoretically).
When you #Autowire a Prototype-scoped Bean inside a Singleton-scoped Bean, that Prototype one becomes a sort-of-singleton. Just think about it; a Singleton gets created, its injectable fields get Autowired, and that is it, the instance lives forever along with all its fields (keep in mind those Prototype-scoped fields are "pure" instances, they're not proxied).
#Lookup
is a proxy-driven annotation. What that means is Spring will extend your class using JDK proxies or CGLIB proxies, and it will override/implement the #Lookup-annotated method, providing its own version which uses a BeanFactory#getBean each time it is invoked.
The documentation is clear on this point
An annotation that indicates 'lookup' methods, to be overridden by the
container to redirect them back to the BeanFactory for a getBean call.
Thus, that means a fresh Bean instance is returned every time.
Just for your knowledge, another approach for working with Prototype-scoped Beans inside "other"-scoped Beans is using ProxyFactoryBean. The only difference is that the proxy is created at configuration-time, and then made available for direct #Autowireing, thus not requiring the definition of a #Lookup method, which sometimes is not wanted (usually by folks that are obsessed with clean code, like me).
I'm using Spring 3.1.1 and in my business logic, I have a loop which requires a new instance of a spring bean (prototype scope) for each iteration.
What is the best method to do this? Must I create my own BeanFactory class which I can inject once into my class, and call upon it every time to produce the bean upon request? When looking at the Spring 3 docs, it seems to imply that I should use ApplicationContext instead. However, using ApplicationContext makes my code Spring dependent.
What is the best method for something like this? Does Spring already provide a factory of sorts that I can leverage?
ApplicationContext is the factory. You don't have to inject it into your class; you instantiate one and use it to create the beans and wire up their dependencies.
I don't understand the comment "using ApplicationContext makes my code Spring dependent." Yes, it does. Do you think DI is worth it or not?
I think you should go with spring. Spring facilitates your need. You can use a method to lookup bean of specific type from application context. So if you make that bean to be prototype. then when you call this special method, you will be returned with a new instance of the bean you want.
You will find it indetails here!
You can use custom scope and make the injecting bean proxy, and on the custom scope bean listen to some dynamic events that can inject the underling proxy bean
I am having an issue when trying to create beans from a spring Application Context inside a bean instantiated by spring using constructor arguments.
I have implemented the ApplicationContextAware interface but it populates the context after the instance is created (obvious).
But then, if you need to get beans from the constructor, and I am talking about a variable number of objects defined at runtime, what would be the correct way to proceed?
In beans instanciated by Spring, instead of initializing it in the Constructor, initialize it in a dedicated method, marked as "init-method" for Spring.
You have about the same effect as initializing in the constructor, but you are using the correct Spring life-cycle.
You can make the context accessible from constructor exploiting aspect-oriented programming. Spring has special support for that - #Configurable(preConstruction = true).
Feel free to read more about that at the spring reference - 6.8.1. Using AspectJ to dependency inject domain objects with Spring