What is the difference between "constructor based injection" and " autowire by constructor mode" in Spring - spring

I know and understand constructor based injection. But, the autowiring modes confuse me.
1) I have read that default mode for autowiring is 'no autowiring' i.e. We have to manually set the properties in xml file. But, isn't xml based configuration a type of autowiring? How can it be considered 'No autowiring'?
2) Other modes for autowiring are i) byName ii) byType iii)constructor iv) auto-detect. Am i correct to assume the following:
a) When using xml configuration based autowiring, the default mode is 'byName'(i.e. I have to keep the name of property reference the same as the name of the bean which is being used as a property.)
b) When using Annotations, default mode is 'byType'( Regardless of the place the #Autowired keyword is placed i.e on the setter, on the constructor or on the property, it will search the type of the property being autowried)
3) What is the difference between constructor based injection and 'constructor' mode of autowiring?(I have read that constructor mode means it applies byType mode on all the constructor arguments, but how is it different from placing #Autowired keyword on the constructor)
4) I know that to enable autowired mode byName in annotations, in the bean definition in the xml file, I have to use " autowire = 'byName' ". But, suppose I am using Annotations only config( using #Component, and no bean definitions in the xml ), and I want to use byName autowire mode, then what is the way of doing that?

I think you are a bit confused. First, you need to understand dependency injection (see here). There is ton of info about DI but in short, it means some third party (e.g spring IOC) passes the dependencies to the objects rather than the objects to create/obtain the references themselves. This could happen either through constructor or setter. For instance, consider constructor DI
class B{
}
class A{
private B b;
public A(B b){
this.b = b;
}
}
Some third party will inject an instance of class B into A rather class A create a reference to B itself. Very often you would use an interface so class A wouldn't even know what object will be injected into it.
Now in Spring there are different ways to configure these associations between the objects (the example above). You can either use XML, Java Config or Autowiring. They are independent but do the same stuff.
In both XML and JAVA config you need to configure the dependencies explicitly - either in xml file or having a #Configuration class for the JAVA Config and annotating the beans with #Bean. The autowiring is different. There you create simple POJOs which you annotate with #Component, #Controller, #Service or #Repository. They will be automatically registered as beans via component scanning. With autowiring you don't need to explicitly configure the dependencies in XML file or JAVA Config class. You can do it in code directly. For instance, if we have to compare java config vs autowiring using the previous example
Java Config (explicit config in a config class)
#Bean
public A getA(){
return new A(new B());
}
Autowiring (implicit - done in code)
#Component
class B{
}
#Component
class A{
private B b;
#Autowired
public A(B b){
this.b = b;
}
}
In the latter we autowire class B into class A (they both will be registered as beans due to #Component annotation) without having explicitly defined this association in an xml file or java config class. I hope it makes sense.

If you have to specify the bean names in the xml, its not happening automatically, hence its not autowiring.
With autowiring spring will figure out what bean to inject even though it may not be explicitly written.
When using xml configuration based autowiring, the default mode is 'byName'
When using Annotations, the ordering that happens depends on the annotation used as there are a few that can be used. #Autowire #Resource #Inject.
When using #Component, the default wiring is of type. The method below will resolve on any autowiring needs for a Service object.
#Bean
public Service getMyService(){
return new Service();
}
If there are multiple #Bean methods that return a Service you will get an error.
If you wanted to do wire via name while using #Component you would add the #Qualifier("nameToUse") annotation to the variable. It would find an #Bean annotated method called getNameToUse().
#Autowired
#Qualifier("nameToUse")
private Service myService;

Related

How Field Injection in Spring Boot works internally?

#Autowired
UserService userService;
What happens exactly inside `#Autowired annotation whether it uses Constructor Injection or Setter Injection. I know that it is field Injection.
I'm not asking How IOC or DI works, I'm asking How Field Injection in Spring Boot works internally?
Basically field inject is a type of injection (obviously), so Spring injects dependency based on field type and maybe some annotations (like #Qualifier).
How does it work?
When Spring creates a bean, there is a special Bean Post Processor org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
Each field marked with #Autowired is considered by spring as a dependency, so it must analyze these dependencies (by using reflection under the hood) and find a match from the application context for each field (by Type, qualifier if specified, etc.). Then it sets the value, right into the field, again by reflection.
I don't intend to start "holly-wars" here, but I'll just mention that I personally try to avoid using this type of injection because it effectively breaks encapsulation of dependencies, making the class with autowired fields non-unit testable.
For example if you have something like this:
#Component
class Foo {
#Autowired
private Bar bar;
public Foo() {} // no-arg construction that exists by default
}
#Component
class Bar {
}
Then when you create an instance of Foo by yourself (e.g. in unit-test) you have no clear way to supply the Bar dependency to Foo instance without relying on spring.
Constructor Injection solves this for example.

Java Configuration vs Component Scan Annotations

Java configuration allows us to manage bean creation within a configuration file. Annotated #Component, #Service classes used with component scanning does the same. However, I'm concerned about using these two mechanisms at the same time.
Should Java configuration and annotated component scans be avoided in the same project? I ask because the result is unclear in the following scenario:
#Configuration
public class MyConfig {
#Bean
public Foo foo() {
return new Foo(500);
}
}
...
#Component
public class Foo {
private int value;
public Foo() {
}
public Foo(int value) {
this.value = value;
}
}
...
public class Consumer {
#Autowired
Foo foo;
...
}
So, in the above situation, will the Consumer get a Foo instance with a 500 value or 0 value? I've tested locally and it appears that the Java configured Foo (with value 500) is created consistently. However, I'm concerned that my testing isn't thorough enough to be conclusive.
What is the real answer? Using both Java config and component scanning on #Component beans of the same type seems like a bad thing.
I think your concern is more like raised by the following use case:
You have a custom spring-starter-library that have its own #Configuration classes and #Bean definitions, BUT if you have #Component/#Service in this library, you will need to explicitly #ComponentScan these packages from your service, since the default #ComponentScan (see #SpringBootApplication) will perform component scanning from the main class, to all sub-packages of your app, BUT not the packages inside the external library. For that purpose, you only need to have #Bean definitions in your external library, and to inject these external configurations via #EnableSomething annotation used on your app's main class (using #Import(YourConfigurationAnnotatedClass.class) OR via using spring.factories in case you always need the external configuration to be used/injected.
Of course, you CAN have #Components in this library, but the explicit usage of #ComponentScan annotation may lead to unintended behaviour in some cases, so I would recommend to avoid that.
So, to answer your question -> You can have both approaches of defining beans, only if they're inside your app, but bean definitions outside your app (e.g. library) should be explicitly defined with #Bean inside a #Configuration class.
It is perfectly valid to have Java configuration and annotated component scans in the same project because they server different purposes.
#Component (#Service,#Repository etc) are used to auto-detect and auto-configure beans.
#Bean annotation is used to explicitly declare a single bean, instead of letting Spring do it automatically.
You can do the following with #Bean. But, this is not possible with #Component
#Bean
public MyService myService(boolean someCondition) {
if(someCondition) {
return new MyServiceImpl1();
}else{
return new MyServiceImpl2();
}
}
Haven't really faced a situation where both Java config and component scanning on the bean of the same type were required.
As per the spring documentation,
To declare a bean, simply annotate a method with the #Bean annotation.
When JavaConfig encounters such a method, it will execute that method
and register the return value as a bean within a BeanFactory. By
default, the bean name will be the same as the method name
So, As per this, it is returning the correct Foo (with value 500).
In general, there is nothing wrong with component scanning and explicit bean definitions in the same application context. I tend to use component scanning where possible, and create the few beans that need more setup with #Bean methods.
There is no upside to include classes in the component scan when you create beans of their type explicitly. Component scanning can easily be targeted at certain classes and packages. If you design your packages accordingly, you can component scan only the packages without "special" bean classes (or else use more advanced filters on scanning).
In a quick look I didn't find any clear information about bean definition precedence in such a case. Typically there is a deterministic and fairly stable order in which these are processed, but if it is not documented it maybe could change in some future Spring version.

How to override a Spring #Autowire annotation and set a field to null?

I am a Spring neophyte who is working on a large Spring-based project that has extensive coupling between Spring beans. I am trying to write some integration tests that exercise subsets of the total application functionality. To do so, I'd like to override some of the autowiring.
For example, suppose I have a class
public class MyDataServiceImpl implements MyDataService {
#Qualifier("notNeededForMyDataServiceTest")
#Autowired
private NotNeededForMyDataServiceTest notNeededForMyDataServiceTest;
//...
}
and a context file with:
<bean id="myDataService"
class="MyDataServiceImpl">
</bean>
In my test, I have no need to use the notNeededForMyDataServiceTest field. Is there some way I can override the #Autowired annotation and set notNeededForMyDataServiceTest to null, perhaps in the XML file? I don't want to modify any of the Java classes, but I do want to avoid the (problematic) configuration of notNeededForMyDataServiceTest.
I tried doing:
<bean id="myDataService"
class="MyDataServiceImpl">
<property name="notNeededForMyDataServiceTest"><null/></property>
</bean>
That doesn't work. IntelliJ informs me "Cannot resolve property 'notNeededForMyDataServiceTest'", apparently because there are no getters and setters for that field.
I'm using Spring Framework 3.1.3.
The following configuration should work, I took the liberty of mixing in Java configuration
#Configuration
//This will load your beans from whichever xml file you are using
#ImportResource("classpath:/path/beans.xml")
public class TestConfigLoader{
// This will declare the unused bean and inject MyDataServiceImpl with null.
public #Bean(name="notNeededForMyDataServiceTest") NotNeededForMyDataServiceTest getNotNeededForMyDataServiceTest(){
return null;
}
... any other configuration beans if required.
}
And annotate your test class like so:
// In your test class applicationContext will be loaded from TestConfigLoader
#ContextConfiguration(classes = {TestConfigLoader.class})
public class MyTest {
// class body...
}
These could help:
Context configuration with annotated classes
Testing with #Configuration Classes and Profiles
Spring TestContext Framework
and profiles:
beans profile="..."
Introducing #Profile
You could create different beans definition in the XML configuration and then activate them using the -Dspring.profiles.active="profile1,profile2" env.
You're using the #Autowired mechanism wrong. The qualifier is not a property that you need to set. That's actually the name of a bean, so that the container will be able to choose one particular instance in case multiple beans of the same type are defined in the same context.
So the container will look for a bean of type NotNeededForMyDataServiceTest and the name (which would actually be the bean id in XML): notNeededForMyDataServiceTest.
What I think you want is to instruct the container to not inject anything in that field if no bean of type NotNeededForMyDataServiceTest is defined in the application context. That could be achieved simply by setting the required attribute of the annotation to false:
#Autowired(required = false)
NotNeededForMyDataServiceTest someOptionalDependency;
The only drawback of this approach would be that the container will never complain at runtime if there's nothing to inject in that field (and perhaps you would want this sanity check when your code runs in production).
If you don't want to make that dependency optional (or you can't edit that code for some reason), you'll need to provide a mock / null value for that field by setting that explicitly in your context. One option to do that would be to use Java configuration instead of XML (like in #Abe's answer) and another approach would be to make use of a factory bean which returns null (like in this question).

How do Spring annotations work?

Motivation
As a follow-up to my previous questions on classloading
How is the Classloader for a class chosen?
How Classloader determines which classes it can load?
Where does bytecode injection happen?
I'm curious about how do annotations work in a popular Spring framework.
Possible solution
As far as I understand, two mechanisms might be used:
1. Bytecode injection on classloading
Spring could use its own classloader to load required classes. At runtime, when the class is loaded and Spring determines it has some appropriate annotation, it injects bytecode to add additional properties or behavior to the class.
So a controller annotated with #Controller might be changed to extend some controller base class and a function might be changed to implement routing when annotated with #RequestMapping.
#Controller
public class HelloWorldController {
#RequestMapping("/helloWorld")
public String helloWorld(Model model) {
model.addAttribute("message", "Hello World!");
return "helloWorld";
}
}
2. Reflection used for instantiation
#Autowired could be read by reflection at runtime by the BeanFactory to take care of the instantiation order and instantiate the configured properties.
public class Customer
{
private Person person;
#Autowired
public void setPerson(Person person) {
this.person = person;
}
}
Question
How do Spring annotations really work?
Spring is open source so you don't need to figure how it work, look inside:
RequestMapping annotation is handled by RequestMappingHandlerMapping, see getMappingForMethod method.
Autowired annotation is handled by AutowiredAnnotationBeanPostProcessor, see processInjection method.
Both use reflection to get annotation data and build the handler mapping info in the first case or populate the bean in the second one.
Spring context understand annotation by set of classes which implements bean post processor interface. so to handle different type of annotation we need to add different annotation bean post processors.
if you add <context:annotation-config> in you configuration xml then you need not to add any annotation bean post processors.
Post processor provide methods to do pre and post processing for each bean initialization.
you can write your own bean post processors to do custom processing by created a bean which implements BeanPostProcessor interface.

Spring DI? Interface Type?

I understand the how, but can't seem formally shape the definitions.
As known DI can be done via constructor or setter or interface.
I am confused about the latest one -interface based DI, is it used in Spring?
UPDATE: I gave bad examle in here, which led to wrong understanding.
To fix it up:
Say we have setter and in setter we inject interface implemented by some class. Is that considered DI via setter or interface?
http://martinfowler.com/articles/injection.html#UsingAServiceLocator
this article divides DI on:
"There are three main styles of dependency injection. The names I'm using for them are Constructor Injection, Setter Injection, and Interface Injection. If you read about this stuff in the current discussions about Inversion of Control you'll hear these referred to as type 1 IoC (interface injection), type 2 IoC (setter injection) and type 3 IoC (constructor injection). I find numeric names rather hard to remember, which is why I've used the names I have here."
Else Service Locator pattern used for IoC, is it the one that actually makes possible #Autowired? - ie that not all classes explicitly need to be declared in xml for DI, as we can declare them as #Repository or #Controller or alike again if I recall correctly.
Thanks,
Autowiring an interface means wire a bean implementing that interface. This relies on an implementation actually existing in the bean factory.
#Autowired
UserService us; // wire a bean implementing UserService
--
#Service
public class UserServiceImpl implements UserService {
// the #Service annotation causes this implementation of UserService to
// be made available for wiring in the bean factory.
}
Worth noting is that if you wire by interface, Spring will expect there to exist one and exactly one bean in the bean factory implementing that interface. If more than one bean is found, an error will be thrown and you will have to specify which bean to wire (using the #Qualifier annotation).
EDIT:
When wiring, you can either wire a member variable or a setter method.
#Autowired
UserService us;
--
#Autowired
public void setUserService(UserService us) {
this.us = us;
}
These two produce the same result. The difference is that in the former, Spring will use reflection to set the variable us to a bean implementing UserService. In the latter, Spring will invoke the setUserService method, passing the same UserService imlementation.

Resources