In several code examples I see autowiring used instead of constructor injection. Can any one explain why Constructor injection is difficult but autowiring is possible on spring configuration classes? Thanks in advance.
this question does touch the topic but doesn't have the detailed answer.
Constructor injection requires all dependencies are available beforehand.
In early Spring Boot (before 2.6) circular dependencies are allowed by default. It is impossible to have circular bean dependencies together with the constructor injection (egg-chicken problem if A => B & B => A and both use it).
I think for this reason such expression of DI dependencies was implemented later. With a default constructor + setter or #Autowired you could resolve circular dependencies.
Related
Is there any difference between Bean Injection and Dependency Injection in Spring, or are they the same?
Since the dependencies are beans in our context, yes we can say that they are the same.
Any dependency that is managed by Spring is called a Spring Bean. When you register a type in Spring, when it is used as a dependency in other objects, it is injected by Spring.
On the other hand, Dependency Injection doesn't need a container like Spring. When you have a method that takes arguments, that argument is a dependency, which is a form of dependency injection instead of hard code the value of the argument in your method.
Can I know what is the difference between dependency injection and autowiring? Whether autowiring is different from dependency injection?
Which is the best way to autowiring(XML based or annotation based)?
Short answer: Dependency Injection is a design pattern, and #autowired is a mechanism for implementing it.
The DI idea is that, instead of your object creating an object it needs (say by using new to instantiate it), this needed object - a dependency - is handed to your object, typically using the constructor or a setter method. If you autowire, you're injecting a dependancy. In this case, Spring uses reflection to make this work, so you're not using the constructor or a setter method, but you're still injecting the dependency.
To answer question 2, its your choice. Personally, I find the XML configuration files cumbersome and use annotations whenever I can. You can accomplish whatever configuration you need to do either way.
I'm a fresher, I'm recently started learning Spring.In spring dependency injection,we
can inject a bean in 2 ways,one is through constructor and the other one is through
setter method.My question is, for what situations constructor injection is better and
for what situations setter method injection is better. my focus only on where to use?
Give me an example if possible... waiting for your valuable reply..
There is a third way: Field injection.
You can directly apply the Annotation #Resource, #Inject or #Autowire at a (even private) field. This field even does not need to hava a getter or setter.
If you are building a Spring application, and there is no plan to use the classes in a not Spring application or a library, then the field injection is enough for 90% of the classes.
I prefer it, because it is less code.
Of course if you use a constructor for mandatory references then there is no way to forget one of them when creating a new instance. But (and this is my point of view, that differs from Alef Arendsen in his 3 year old Spring 2.0 blog entry "Setter injection versus constructor injection and the use of #Required") you have a spring bean and not a simple class. And this bean is created by spring, not directly by you. So if you use #Resource, #Inject or #Autowire for fields or setter spring checks them too and do not put the bean and the whole application in service if not all references can be satisfied.
I'd say go for constructor injection.
In some cases go for setter injection if dependency is optional.
If you forced to use setter injection and use Spring, the use #Required to ask Spring to enforce it.
Apply common sense in all cases :)
I have a set of Spring beans created using constructor injection. Since there are (by design) circular references to other beans, I'd like to post-process the beans once they are all created to inject the references to other beans.
Initial attempts at using BeanPostProcessor show that the BeanPostProcessor is running after EACH bean is instantiated, not waiting until all have been instantiated.
Does Spring provide a mechanism for post-processing as set of beans after all have been created?
If you're creating the beans in an ApplicationContext, the ApplicationContext fires ApplicationEvents to any registered ApplicationListener callbacks. One of those should tell you when all the beans in the context are wired together via Spring.
Here's what the documentation says about circular dependencies:
If you use predominantly constructor injection, it is possible to
create an unresolvable circular dependency scenario.
For example: Class A requires an instance of class B through
constructor injection, and class B requires an instance of class A
through constructor injection. If you configure beans for classes A
and B to be injected into each other, the Spring IoC container detects
this circular reference at runtime, and throws a
BeanCurrentlyInCreationException.
One possible solution is to edit the source code of some classes to be
configured by setters rather than constructors. Alternatively, avoid
constructor injection and use setter injection only. In other words,
although it is not recommended, you can configure circular
dependencies with setter injection.
Unlike the typical case (with no circular dependencies), a circular
dependency between bean A and bean B forces one of the beans to be
injected into the other prior to being fully initialized itself (a
classic chicken/egg scenario).
I would just use setter injection in this case, or try to avoid the circular dependency in the first place. Another solution is to make one of the beans BeanFactoryAware, and to lookup the other bean from the bean factory when the reference is needed.
I have two maven projects say MvnSpring and MvnGuice.MvnSpring is working on spring and hibernate frame works.
And MvnGuice is working on google guice and mybatis. I need to combine both the features together.
Both are following singleton pattern. I need to get some class of MvnSpring in MvnGuice while coding. So that I created a jar of MvnSpring and put it in .m2 repository and give the dependacy details in MvnGuice. Now I can import classes of MvnSpring in MvnGuice classes.MvnSpring uses spring dependency injection and MvnGuice uses guice dependency injection for object creation. Now in MvnSpring flow is MSserviceImpl(implements MSservice) > MSdaoImpl(implements MSdao). Now I need to call MSService class from MvnGuice. Then at run time it shows error like MSService class is null. Then I made a guice dependency injection for MSService class in MvnGuice. Now the control reaches MSserviceImpl but now MSdao is null at here. Is it possible to start MvnSpring along with MvnGuice. I hope then I can solve the issue.
While Spring and Guice are targeted at the same problem, IoC, they take very different approaches to solve it. They differ both in functionality and in how they are configured, where Spring has bean definitions and Guice uses bindings.
Fortunately they do have common grounds in that they both support JSR-330, a standards specification that defines a set of annotations. This enables you to write your singletons and describe the injections that they need without depending on either Spring or Guice.
This way you can share your singletons between projects irregardless of the framework you use in a particular project. I would not recommend using both Guice and Spring in the same project, except if there's a clearly defined separation between them. For instance you might use Guice for a module that is used by Spring code via a defined API that hides the fact that it internally is based on Guice.
There was already mentioned JSR-330.
For some cases it can be not enough, e.g., you have code:
final String className = config.getProperty(«serviceImpl»);
// Class.forName(name) and check required interface for type safety
final Class<? extends Service> serviceClass = Reflection.classForName(className, Service.class);
final Service service = injector.getInstance(serviceClass);
In different DI environments you are supposed to support both com.guice.inject.Injector.getInstance() and org.springframework.context.ApplicationContext.getBean() implementations.
There is the draft solution sdif4j Simple Dependency Injection Facade.
The idea of this project is to encapsulate different DI frameworks logic with own abstraction to extend default JSR-330 possibilities. Note, there is no public releases yet, but you can find ideas how to solve your problem or make an internal release in a fork.
The general issue, is that your both MvnSpring and MvnGuice projects are supposed to be based on JSR-330 (instead of guice/spring annotations) and org.sdif4j:sdif4j-api (or your own abstraction; only if Injector functionality is required). It is recommended to make guice and spring dependencies optional (to compile but not export) to allow the library clients to choose the DI themselves.
In your MvnCompineGuiceAndSpring you just declare sdif4j-guice or sdif4j-spring dependency (it is similar to slf4j usage) and configure your DI environment. You can find different examples in testing subproject.
Some more notes:
Spring default scope is singleton, Guice - prototype (Spring terminology). So, if you want a prototype bean, you can use:
#org.springframework.context.annotation.Scope("prototype")
#javax.inject.Named
public class TestPrototype {
}
The Spring #Scope annotation should be ignored by guice even if spring does not present in your classpath.
Also you have to declare all your Singleton beans with #javax.inject.Named and #javax.inject.Singleton annotation to support both Spring and Guice, like this:
#javax.inject.Named
#javax.inject.Singleton
public class TestSingleton implements ITestSingleton {
public TestSingleton() {
}
}
As with #Scope annotation, you can use #ImplementedBy(#ProvidedBy) guice annotations on your code (when feasible; be careful with it, in general it is not a good practice), that should be also ignored in Spring DI (in both cases if Spring exists in classpath or not).
Hope, that's clear.