How is dependency injection working? - java

I am reading the Pro Spring 2.5 book and I have a question to how dependency injection works.
I understand the BeanFactory and doing dependency lookups. Now I read about dependency injection and I have some questions. Based on what I understand you want to limit the lookups to the minimum such as looking up an object for boot strapping the application. Then dependency injection will take care of the rest. However I don't understand this works.
Let say you have a beanfactory, you get an MyApplication instance that starts the whole application. The rest of the objects use dependency injection to get their collaborators. The beanfactory maintains the list of beans it manages but isn't this factory only available in the main method of the application? And if the beanfactory also manages the scope of their containing beans I don't understand how that is done. Are the beanfactory global in some way?

The bean factory instantiates all objects. It parses your configuration (xml or annotations), instantiates your beans and sets their dependencies. Then all these beans are stored in the application context.
You usually have an entry point to your application - there you do context.getBean(..). Now that bean has its dependencies injected, because it is put in the context by the bean factory.
The rule of thumb that will probably clear things: you never use the new operator (with bean classes) when using a DI framework. The framework makes the instances, not you.

So, there are two ways this can happen (as of Spring 3). In "traditional" dependency injection, the bean factory can only inject dependencies into beans it creates itself. In this scenario, the bean factory will resolve and inject all dependencies of a bean when that bean is first created.
The other way requires you to employ "full" AspectJ with either load- or compile-time weaving. In this scenario, you use an aspect in the spring-aspects.jar that basically pointcuts all new operations, allowing you to get dependency injection in arbitrarily created objects. This is triggered by using the #Configurable annotation. You can read more here.

The whole point on inversion of control and dependency injection is that you (typically) don't need the beanfactory except to get your application started. Your dependencies "automatically appear" in your objects. This is basically intended for objects with very few, typically one, instance during the whole lifetime of your application.
E.g. if your MyApplication depends on an instance of MyModuleA, you can simply have it #Autowired. When you fetch the application object from beanfactory at start time it already comes with an instance of MyModuleA preset.
About the scopes: this comes from web context. Besides objects with only one instance ever you can have objects scoped to a user's session. There you can store information you need to keep over several requests but separate for different users, think: shopping cart.
Typically treat the bean factory as global. I think it would be possible to have several instances, but they would be disconnected and can't inject objects only known to other instances.

Related

Bean created by spring are used by all calls. what if in any one call i updated some context will that be available to any other call to spring app

Spring created a bean if I change a local variable of that class. forex - I change a variable value.
will that new value be available for any new thread or call to spring application api.
Spring beans are created for the purpose of dependency injection. That means, you don't pass these bean objects as parameters nor do you change these beans as they are singleton in nature. These beans are injected in corresponding classes where their properties and methods could be used.
And, if you are changing these beans in some method, then the entire fundamental of making beans for the purpose of dependency injection will be breached.
Hope this clarifies your doubt.
Also, if it is not what you asked, can you please share some codeblock where the things could be more clear?

How much overhead does prototype scope cause?

My understanding is that a prototype-scoped Java bean class is instantiated every time it is requested, as opposed to singleton-scoped Java beans which are instantiated once when the application starts up.
My question is: how much overhead does using the prototype scope cause?
Does the Spring framework make any attempt to recycle prototype-scoped objects to reduce the overhead caused by repeated instantiation?
Is the overhead caused by prototype scoping enough to warrant efforts to make as many of my Java bean classes stateless so that I can apply singleton scope to them?
You should not think of overhead between the prototype and singleton scope, but only the way they are used. If they are stateless objects that will live throughout the life time of the application, the correct scope is singleton. Many beans exist in that scope, for example controllers, beans in a service or persistence layer. Most beans related to Spring Security framework are also stateless and live in singleton scope.
If you want to create a brand new bean for a specific processing and then discard it when it has been used, then it is a use case for the prototype scope. As I mainly used spring for Web application I seldom used prototype scoped beans, but used request scoped beans which have a close use case: they are created for a HTTP request processing. The only point of attention is that if you have to inject a prototype or request scoped bean in a singleton bean, you will have to use a proxy that allows to connect to the current prototype bean (may be in thread storage) and not a bean that would have been created when the singleton was.
Using prototype scope is the same as if you were to instantiate using 'new' except that the new object will be managed by Spring. Spring will be able to apply aspects, inject dependencies, etc.. There will also be the overhead of the proxy class created to wrap the object.
Spring will not attempt to reuse the instances.
If you do not want to create a new instance whenever you reference the bean then you should not be using a prototype. Your solution will either require independent instances, maybe due to concurrency, or it will allow for a singleton. It is unlikely that the memory used by the object will be the deciding factor for what scope you use.

Spring - Using factory-bean types with lookup-method

Okie is have some third party code running on Spring 3.1.4 and I cannot change that. Also the code uses lookup-method to inject a type dynamically at runtime. This type is of a prototype scope. All is standard Spring usage of lookup-method based service object creation.
Problem is that on 3.1.4 there is a lot of blocking on DefaultSingletonBeanRegistry because of the synchronized block there in getSingleton method. The thread dumps show that the execution path reaches there when a lookup-method based inject is required and get stuck there till they get the time to run through.
I was wondering if I can use a factory-bean to create those prototype beans instead of defining them as a prototype bean itself. Inside the factory-method of the factory bean i would use the new constructor_call() based approach to instantiate the value beans. And also keep the bean id of the factory-bean same as the prototype bean in the third party cpring configuration XML.
would this approach work?
And also keep the bean id of the factory-bean same as the prototype
bean in the third party cpring configuration XML.
I don't think this would work. If you have two beans with the same name (the one you define plus the one presumably defined in the 3rd party's config) you'll get an exception.
However, I think you could use a BeanDefinitionRegistryPostProcessor to remove the prototype scoped bean and replace it with a bean of your own design.

what is meant by context in CDI?

I am new to CDI. While reading, I am always encountering contextual objects, non contextual objects. What does they mean?
For example the below link
http://docs.jboss.org/weld/reference/latest/en-US/html/beanscdi.html#d0e881
Message-driven and entity beans are by nature non-contextual objects
and may not be injected into other objects
The context of a CDI framework is basically a big map of objects*. You can add objects to the context or make the CDI framework create objects from your service classes by using any CDI configuration method (spring xml beans/annotations like #Component/#Service).
Once you have the context you can get objects from it: (Spring: getBean(name))
Now you can configure dependencies between the objects/beans in the context, and the CDI will make sure any object you get from the context will have its dependencies set. This is the dependency injection part.
Non-contextual objects are simply not added to the context and the CDI framework does not know about them. Usually only service classes are part of the CDI context.
* Not really a map though, objects can be accessed by name, by type and other ways. The default is you get the same object each time you ask by the same name (singleton), although you may configure the CDI to create a new object each time you ask (prototype).
A context in CDI is some span during execution of your program when contextual objects can be used.
It defines when CDI container creates, destroys and how it links instances of those objects together.
Non-contextual objects are those that are not tied to any CDI context.
MDBs are one example, they are managed by EJB container and not intended to be used as ordinary objects.
Entities come and go as you interact with a DB via JPA, so they also cannot be tied to a context.
Another example is any object whose instances you create manually.

Adding behaviour using Spring

I have a bunch of projects which declare some spring bean files. I would like to write a "library" which supplies a utility which takes some bean names and adds some behaviour "around" the objects (example: Call Counting, Monitoring, Logging etc)
One obvious way for doing this would be to add some AspectJ annotations in the spring xml files in the projects but I would like the "utility" to search for some beans and add behaviour to them (This way the projects themselves are not aware of the utility).
The utility will be declared in the spring xml file somewhere so it has access to the ApplicationContext as it could implement ApplicationContextAware interface however I am keen on exploring how one would go about modifying behaviour of another bean in the app context programmatically. ex, something like find a bean of id "OrderService", create an aspected bean with some monitoring/call counting etc around all methods and replace that bean in the application context for "OrderService"
I know there are disadvantages with this approach but what I am after is "IS it possible to do this? And if yes how?"
If you don't want to use AOP, you can achieve this using a BeanPostProcessor. The Spring documentation states:
The BeanPostProcessor interface defines callback methods that you can
implement to provide your own (or override the container's default)
instantiation logic, dependency-resolution logic, and so forth. If you
want to implement some custom logic after the Spring container
finishes instantiating, configuring, and otherwise initializing a
bean, you can plug in one or more BeanPostProcessor implementations.
So you may create and register a BeanPostProcessor and implement the postProcessAfterInitialization(Object bean, String beanName) method to modify the methods you want to customize. Here is an example.
(But I would still recommend that you do this with AOP as this is the classical use case for it and it's much easier and more declarative. With the bean() pointcut, you can even advise beans with names matching a certain pattern.)
You can create your own BeanPostProcessor. You just have two declare it in applicationContext.xml and it will be called for each bean during initialization of beans (in fact, just before or just after). In each call you get a the actual object and its name. There, you can, for example, wrap that object depending on its name or type.

Categories