In simple layman's terms what does getBean do in Spring? - java

Consider a line of code like this
AutomobileDriver ad=(AutomobileDriver)appContext.getBean("increaseSpeed");
Assume there is an IncreaseSpeed class which inherits from AutomobileDriver class
What does getBean do? What is the main function of this?

In "simple layman's terms":
This assumes that Spring was told to create an object instance (possibly in an XML config file) that is identified (by Spring) as with the id "increaseSpeed" and has a class or parent class of AutomobileDriver.
You are asking the Spring context for a reference to (a) by default, the previously created object (this is called a singleton) or (b) a new instance of that object (prototype).

In Spring, you can define a bean and give it an id. Usually, Spring would prefer that you use dependency injection to access the bean. However, Spring provides getBean as another way to access a bean by its id.
Basically, your code will return an instance of the bean with id "increaseSpeed".

This code is requesting the bean named increaseSpeed from the Spring Application Context. Think of the application context as the pool of available objects, which has been configured from your Spring configuration XML. When the application context is started, it creates the beans in the configuration. This call simply asks for the one which is already there. The application context returns this "bean" as a java.lang.Object so you have to cast it to the appropriate type.
You might see this call as an entry point in a Spring application. This call is needed to get the first object out from the application context - from there, this object may have links to other objects which have been injected by Spring.

A bean is a component that provides some functionality, the name of the bean indicates that it would be increase speed.
Those components are registered in a context called 'application context' and can be looked up by name. So if you want to increase the speed look at your apps-context for something that could do this.
More tecnical:
http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/

Related

Why do we need #Lookup, whats wrong with scope=prototype?

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).

How to change instance (target) under CDI (Weld) proxy without proxy recreation

I want to refresh bean (destroy, initialize) if some property is changed, for example db url connection. The problem is that this bean might be already injected in other beans in CDI container. I have 2 thoughts about this:
1. If bean is proxied - destroy target for this proxy, re-initialize target inside this proxy.
2. For #Singleton and #Dependent beans, because they are not proxied, I can wrap such beans in proxy and do the same as above.
The reason I want to wrap it in proxy is that when property changed and I want to recreate real object, I should also know all dependent beans that have dependency on my bean.
So my questions are:
1. How to replace real object inside proxy in CDI? or
2. If I dont want to keep proxy as I explained above, how to create proxy object for my bean and re-inject it to all dependent beans in CDI container?
This is my previous question:
Re-inject CDI bean if some injected property changed
Again, I use CDI (Weld), not Spring IoC, so I can not use #RefreshScope from Spring cloud config, but I think my expected functionality can be similar with using custom scope.
For #DependedSCoped beans you can use
class MyBean {
#Inject
private Instance<MYType> myTypeInst;
// This will ensure, that the bean is always fresh created.
// But the property value on the former instance will be lost
// So the changable value has to be provided another way to the created bean
public void do SomeThing(){
MyType bean = myTypeInst.get();
myTypeInst.destroy(bean);
}
}
If you use a #Depended scoped bean, then you must be aware that the injection target gets its instance which is exclusively for this bean, so who is changing the value? Is the #Dependend scope the right scope for your use case?
It should not be necessary to provide an own proxy or hack into an existing one, just find the proper scope for your use case and implement the bean properly. If a connection url can change then the bean managing the connection must be aware of a change and recreate the connection and the beans using this bean need to retrieve the connection each time the use it.
Maybe you could provide an description of your use case, then we maybe can you provide you with an better answer.
Conclusion
As the use case became clear (see comments below), it resulted in the intention to implement a custom scope, because CDI doesn't seem to provide a suitable scope for this use case. I recommend to try to find a provided CDI scope if possible and implement a custom scope only if necessary, because you will have to take care about the lifecycle of your beans, management of your scope and how the beans, managed by your scope, can and will be used by an application. If not implemented with care a custom scope could cause problems such as memory leaks, if for instance your beans are not properly discarded after usage.

How to inject spring bean (prototype scope) dynamically

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

Get access to all spring beans of a given type

I have a Spring application (Spring Batch not web application). In a test class, I want to grab access to all of my beans of a given type.
I understand that in Spring you should generally use IOC and let the container inject your beans. However in this case, I want to loop through a variable number of beans that extend a given class (org.springframework.batch.item.database.JdbcCursorItemReader), and do something (want it to be a unit/integration test that just connects it to the database and reads 1 row, so we can confirm at test time that all of the JdbcCursorItemReader in the system have valid SQL and row mappers).
Problem 1) I can only get beans one at a time. I can have my class implement BeanFactoryAware to get a reference to my beanfactory. Then I can do beanFactory.getBean("name"); to get access to a single bean. How do I instead get ALL beans? I can loop through and drop the ones that aren't the class I want.. but somehow I need a list of all beans the beanfactory knows about or something.
Problem 2) The bean I get back from the beanfactory is a proxy. If I try to cast and use my bean I get something like
java.lang.ClassCastException: $Proxy0 cannot be cast to org.springframework.batch.item.database.JdbcCursorItemReader
You can get around the first problem by using ApplicationContextAware instead of BeanFactoryAware. This will pass in the ApplicationContext, which has the getBeansOfType() method which lets you retrieve all beans that are of a given type.
The second problem is likely caused because something is creating AOP proxies around your JdbcCursorItemReader bean. These generated proxies will, by default, implement the same interfaces that JdbcCursorItemReader does (specifically, ItemReader and ItemStream). Your code should not try and cast to the class type (JdbcCursorItemReader), but to one of those interface types instead. It's usually possible to force the proxy to extend the proxied class directly, but without knowing anything about your setup, I can't help you with that.

Spring Application Context available inside the constructor

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

Categories

Resources