Why we need Dependency Injection?
Its to overcome monotony behavior. If you are asking for Apple(from Apple.java) you would be served apple object. If you are asking for Mango(from Mango.java) you would be served mango object. Now in case, you are having Fruit and now you are asking Fruit(from Fruit.java) you would be served either apple or mango. Lets take a simple example as below

  1. I have a banking application where I have Account Interface with calculateIntereest Method
  2. I have different account types like SavingsAccount, PersonalLoanAccount and vehicleLoanAccount, HousingLoanAccount
  3. I have a Customer class where he would own a particular account type which wont be known until runtime

Accounts.java

package com.mugil.core;

public interface Accounts 
{
 public Integer calculateInterest();
}

SavingsAccount.java

package com.mugil.core;

public class SavingsAccount implements Accounts 
{
 public Integer calculateInterest() 
 {
  return 8;
 }
}

Customer.java

package com.mugil.core;

public class Customer {
 Accounts accountType;

 public Customer(Accounts paccountType) {
  this.accountType = paccountType;
 }

 public Accounts getAccountType() {
  return accountType;
 }

 public void setAccountType(Accounts accountType) {
  this.accountType = accountType;
 }
}

GetInterestFactory.java

package com.mugil.core;

public class GetInterestFactory {
 Accounts objAccount = null;

 public static void main(String[] args) {
  GetInterestFactory objGetInterest = new GetInterestFactory();
  objGetInterest.showInterestRate();
 }

 public void showInterestRate() {
  String strAccType = "Savings";

  switch (strAccType) {
   case "Savings":
    this.objAccount = new SavingsAccount();
    break;
   case "Vehicle":
    this.objAccount = new VehicleLoanAccount();
    break;
   default:
    this.objAccount = new SavingsAccount();
    break;
  }

  System.out.println("Interest Rate - " + this.objAccount.calculateInterest());
 }
}

Output

Interest Rate - 8
  1. In the above java code we decide the Account Type only when the switch case is executed
  2. Until then the account type is kept as generic value using interface

Now what spring does is the same code can be rewritten to determine the Account Type during runtime in setters and constructors as below

Dependency Injection without Spring using Java Constructor

  1. I have created a new class VehicleLoanAccount.java which has a different interest rate
  2. Now I am going to decide the account type in the Person.java in its constructor as below

VehicleLoanAccount.java

package com.mugil.core;

public class VehicleLoanAccount implements Accounts {
 public Integer calculateInterest() {
  return 11;
 }

}

Dependency Injection without Spring using Java Constructor
GetInterestConsWithoutSpring .java

package com.mugil.core;

public class GetInterestConsWithoutSpring {
 public static void main(String[] args) {
  Customer objPerson = new Customer(new SavingsAccount());
  System.out.println("Interest Rate - " + objPerson.getAccountType().calculateInterest());
 }
}

Output

Interest Rate - 11

Dependency Injection without Spring using Java Setter

  1. Now I am going to decide the account type in the GetInterest.java in its setter method
  2. I would be passing the value of the actual type inside the setter at runtime to decide the account type
  3. The Only thing which I have changed in the addition of new constructor to the Customer Class
  4. Setter method would be passed with specific account type during runtime

Customer.java

package com.mugil.core;

public class Customer {
 Accounts accountType;

 public Customer(Accounts paccountType) {
  this.accountType = paccountType;
 }

 public Customer() {}

 public Accounts getAccountType() {
  return accountType;
 }

 public void setAccountType(Accounts accountType) {
  this.accountType = accountType;
 }
}

Dependency Injection without Spring using Setter Method
GetInterestSettWithoutSpring .java

package com.mugil.core;

public class GetInterestSettWithoutSpring {
 public static void main(String[] args) {
  Customer customer = new Customer();
  customer.setAccountType(new SavingsAccount());
  System.out.println("Interest Rate - " + customer.getAccountType().calculateInterest());
 }
}

Output

Interest Rate - 8

Ways of Bean Injection using Spring
In Spring we can let the container create the bean in two ways

  1. Bean definition in XML
  2. Bean definition using @Component
  3. Bean definition using Java

Bean definition in XML
beans.xml

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context-2.5.xsd">
	<bean id="customer" class="com.mugil.core.Customer" autowire="constructor">				
	</bean>
	<bean  id="savingsType" class="com.mugil.core.SavingsAccount"/>
	<bean  id="vehicleLoanAccount" class="com.mugil.core.VehicleLoanAccount"/>		
</beans>

context:component-scan used for detecting bean
Bean definition using @Component
beans.xml

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context-2.5.xsd">
	<context:annotation-config />
	<context:component-scan base-package="com.mugil.core"></context:component-scan>			
</beans>

@Component marking bean
Customer.java

package com.mugil.core;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

@Component
public class Customer 
{

 @Autowired
 @Qualifier("savings")
 Accounts accountType;
.
.
.
}

@Component marking bean
SavingsAccount.java

package com.mugil.core;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component
@Qualifier("savings")
public class SavingsAccount implements Accounts
{	
	public Integer calculateInterest() 
	{
		return 9;
	}
}

Bean definition using Java

Ways of Bean Injection using Spring
Now, what if we do the same thing from XML and using annotations. Spring offers 3 ways by which dependency injection could be done

  1. XML
    1. Constructor
    2. Setter
    3. Autowiring
      1. byType
      2. byName
      3. Constructor
      4. No
  2. Annotation Based
    1. byType
    2. byName
  3. Java Based

Constructor Based – Dependency Injection using XML

  1. In the below code beans are loaded when the application is deployed and the JVM starts
  2. The beans are uniquely identified using their IDS, in our case it is customer
  3. The parameter for constructor is defined inside constructor-arg in XML

Beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
   <bean id="customer" class="com.mugil.core.Customer">
      <constructor-arg>
         <bean id="savingAccount" class="com.mugil.core.SavingsAccount" />
      </constructor-arg>
   </bean>
</beans>

GetInterestConsWithSpring.xml

package com.mugil.core;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class GetInterestConsWithSpring {
 public static void main(String[] args) {
  ApplicationContext context = new ClassPathXmlApplicationContext("SpringBeans.xml");

  Customer customer = (Customer) context.getBean("customer");

  System.out.println("Interest Rate - " + customer.getAccountType().calculateInterest());
 }
}

Output

Interest Rate - 8

Setter Based – Dependency Injection using XML

  1. For setter injection the only things we need to change is XML
  2. XML should be modified to take value by setter rather than constructor as before using property tag

Beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
   <bean id="customer" class="com.mugil.core.Customer">
      <property name="accountType" ref="savingAccount" />
   </bean>
   <bean id="savingAccount" class="com.mugil.core.SavingsAccount" />
</beans>

GetInterestSettWithSpring.xml

package com.mugil.core;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class GetInterestSettWithSpring {
 public static void main(String[] args) {
  ApplicationContext context = new ClassPathXmlApplicationContext(
   "SpringBeans.xml");

  Customer customer = (Customer) context.getBean("customer");

  System.out.println("Interest Rate - " + customer.getAccountType().calculateInterest());
 }
}

Output

Interest Rate - 8

Autowiring byName

  1. In autoWiring byName the Name of the Instance Varable(accountType) and the ID of the bean in XML should be same
  2. If there is no bean matching the name is found it will throw NullPointerException

Customer.java

package com.mugil.core;

public class Customer {
 Accounts accountType;

 public Customer(Accounts paccountType) {
  this.accountType = paccountType;
 }

 public Customer() {}

 public Accounts getAccountType() {
  return accountType;
 }

 public void setAccountType(Accounts accountType) {
  this.accountType = accountType;
 }
}

Beans.xml

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
	<bean id="customer" class="com.mugil.core.Customer" autowire="byName">				
	</bean>
	<bean id="accountType" class="com.mugil.core.SavingsAccount"/>
	<bean id="vehicleLoanAccount" class="com.mugil.core.VehicleLoanAccount"/>
</beans>

Output

Interest Rate - 9

What if Bean of Correct Name is notdefined in XML? Inour case it is account Type
Beans.xml

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
	<bean id="customer" class="com.mugil.core.Customer" autowire="byName">				
	</bean>
	<bean id="savingAccount" class="com.mugil.core.SavingsAccount"/>
	<bean id="vehicleLoanAccount" class="com.mugil.core.VehicleLoanAccount"/>
</beans>

Output

Exception in thread "main" java.lang.NullPointerException
	at com.mugil.core.GetInterestConstAutoWiringXML.main(GetInterestConstAutoWiringXML.java:13)

Autowiring byType

  1. In autoWiring is byType then there should be at least one bean defined for the matching type, in our case it is Accounts
  2. If there is no bean defined of the type then it will throw null pointer exception
  3. If there is more than one matching bean of the same type is found it will throw No unique bean of type

Beans.xml

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
	<bean id="customer" class="com.mugil.core.Customer" autowire="byType">				
	</bean>
	<bean id="savingsType" class="com.mugil.core.SavingsAccount"/>
</beans>

Output

Interest Rate - 9

What if No bean of right Type is defined in XML or More than one bean of same type defined?
Beans.xml
No bean of right Type is defined in XML

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
	<bean id="customer" class="com.mugil.core.Customer" autowire="byType">				
	</bean>
</beans>

Output

Exception in thread "main" java.lang.NullPointerException
	at com.mugil.core.GetInterestConstAutoWiringXML.main(GetInterestConstAutoWiringXML.java:13)

Beans.xml
More than one bean of same type defined

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
	<bean id="customer" class="com.mugil.core.Customer" autowire="byType">				
	</bean>
	<bean id="savingsType" class="com.mugil.core.SavingsAccount"/>
	<bean id="vehicleLoanAccount" class="com.mugil.core.VehicleLoanAccount"/>
</beans>

Output

Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'customer' defined in class path resource [SpringBeans.xml]: Unsatisfied dependency expressed through bean property 'accountType': : No unique bean of type [com.mugil.core.Accounts] is defined: expected single matching bean but found 2: [accountType, vehicleLoanAccount]; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [com.mugil.core.Accounts] is defined: expected single matching bean but found 2: [accountType, vehicleLoanAccount]

Autowiring Contructor

  1. In autoWiring using Constructor spring tries to find bean using type.In our case it is Account type
  2. If there is no bean defined of the type then spring will not guess and it will throw null pointer exception
  3. If there is more than one matching bean then spring will not guess and it will throw null pointer exception
  4. If there is more than one constructor spring wont guess the bean and it will throw null pointer exception

Beans.xml

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
	<bean id="customer" class="com.mugil.core.Customer" autowire="constructor">				
	</bean>
	<bean id="savingsType" class="com.mugil.core.SavingsAccount"/>
</beans>

Output

Interest Rate - 9

Beans.xml
Two bean of same type in constructor injection

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
	<bean id="customer" class="com.mugil.core.Customer" autowire="constructor">				
	</bean>
	<bean id="savingsType" class="com.mugil.core.SavingsAccount"/>
<bean id="vehicleLoanAccount" class="com.mugil.core.VehicleLoanAccount"/>
</beans>

Beans.xml
No bean of matching type in constructor injection

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
	<bean id="customer" class="com.mugil.core.Customer" autowire="constructor">				
	</bean>
</beans>

Output

Exception in thread "main" java.lang.NullPointerException
	at com.mugil.core.GetInterestConstAutoWiringXML.main(GetInterestConstAutoWiringXML.java:13)

Autowiring using autodetect
When the bean is configured to autowire by autodetect spring will attempt to autowire by constructor first.If no suitable constructor to bean is found then spring will attempt to autowire byType.
Beans.xml

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
	<bean id="customer" class="com.mugil.core.Customer" autowire="autodetect">				
	</bean>
</beans>

Annotation Based – byType

  1. In Annotation based autowiring the beans would be injected by xml and would be available in container
  2. context:annotation-config is used to activate annotations in beans already registered in the application context (no matter if they were defined with XML or by package scanning)
  3. Now by using @Autowired tag we inject the bean as dependency where it is required.It is used either over variable in class or over setter or over constructor
  4. The default @Autowired decides the bean based on its type.If more than one bean if found it will throw no unique bean found exception.If no bean found it will throw nullpointer exception
  5. Incase of more than one bean of same type, we can narrow down the selection by using @Qualifier annotation and converting to byName @Autowiring

Beans.xml

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context-2.5.xsd">

	<context:annotation-config />
	<bean id="customer" class="com.mugil.core.Customer" autowire="constructor">				
	</bean>
	<bean id="savingsType" class="com.mugil.core.SavingsAccount"/>	
</beans>

Customer.java

package com.mugil.core;

import org.springframework.beans.factory.annotation.Autowired;

public class Customer 
{
 @Autowired
 private Accounts accountType;

 public Customer(Accounts paccountType) {
  this.accountType = paccountType;
 }

 public Customer() {}

 public Accounts getAccountType() {
  return accountType;
 }
 
 public void setAccountType(Accounts accountType) {
  this.accountType = accountType;
 }
}

Annotation Based – byName

  1. In the below code we have two bean of same type
  2. Using @autowired would try to find bean byType.Since there are two beans it would throw no unique bean found exception
  3. Now we need to use @Qualifier passing the name (or) id of the bean as parameter
  4. Incase only Id of bean is there then same would be taken for name, If Name is there then name of bean would be given preference, incase no bean matches name then Id would be given preference

Beans.xml

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context-2.5.xsd">

	<context:annotation-config />
	<bean id="customer" class="com.mugil.core.Customer" autowire="constructor">				
	</bean>
	<bean name="savings" id="savingsType" class="com.mugil.core.SavingsAccount"/>
	<bean name="vehicle" id="vehicleLoanAccount" class="com.mugil.core.VehicleLoanAccount"/>		
</beans>

Customer.java

package com.mugil.core;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

public class Customer 
{

 @Autowired
 @Qualifier("savings")
 Accounts accountType;
.
.
.
}

The below code will work by taking bean id into consideration despite the name doesn’t match.
Customer.java

package com.mugil.core;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

public class Customer 
{

 @Autowired
 @Qualifier("savingsType")
 Accounts accountType;
.
.
.
}

What if there are two bean with the Same Name?
It will not throw exception during compilation but during runtime it will throw bean name already in use exception
Output

Exception in thread "main" org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Bean name 'savings' is already used in this file
Offending resource: class path resource [SpringBeans.xml]

What if there are two bean with the Same ID?

  1. Eclipse will complain for violating ID should be unique and you are violating
  2. If you build the code still builds but when you run will endup with Caused by: org.xml.sax.SAXParseException; lineNumber: 13; columnNumber: 69; cvc-id.2: There are multiple occurrences of ID value ‘savingsType’

Beans.xml

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context-2.5.xsd">

	<context:annotation-config />
	<bean id="customer" class="com.mugil.core.Customer" autowire="constructor">				
	</bean>
	<bean id="savingsType" class="com.mugil.core.SavingsAccount"/>
	<bean id="savingsType" class="com.mugil.core.VehicleLoanAccount"/>		
</beans>

Using @Component Scan to detect and load beans

  1. We can make spring to detect beans on its own by using @component annotation rather then defining in XML with bean tags
  2. Using context:component-scan with base package pointed to beans package will load the bean marked with @component annotation
  3. If there is bean of one type then it would work fine during autowiring, if there is more than one bean of same type then we should uniquely identify the bean using @qualifier annotation
  4. @qualifier annotation should be used both in the place where the bean is referred and also in the place where it is defined.In our case it is Customer.java and SavingsAccount.java

Beans.xml

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context-2.5.xsd">
	<context:annotation-config />
        <context:component-scan base-package="com.mugil.core"></context:component-scan>	
</beans>

Customer.java

package com.mugil.core;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

@Component
public class Customer 
{

 @Autowired
 @Qualifier("savings")
 Accounts accountType;
.
.
.
}

SavingsAccount.java

package com.mugil.core;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component
@Qualifier("savings")
public class SavingsAccount implements Accounts
{	
	public Integer calculateInterest() 
	{
		return 9;
	}
}

In Spring MVC Exceptions can be handled at three levels.

1.Controller Based
We can define exception handler methods in our controller classes. All we need is to annotate these methods with @ExceptionHandler annotation. This annotation takes the Exception class as an argument. So if we have defined one of these for Exception class, then all the exceptions thrown by our request handler method will have handled.
These exception handler methods are just like other request handler methods and we can build error response and respond with a different error page. We can also send a JSON error response, that we will look later on in our example.

@ExceptionHandler({SpringException.class})
.
.
@RequestMapping(value = "/addStudent", method = RequestMethod.POST)
@ExceptionHandler({SpringException.class})
public String addStudent(@ModelAttribute("HelloWeb") Student student, ModelMap model) 
{
 if (student.getName().length() < 5)  
  throw new SpringException("Given name is too short");
 else
  model.addAttribute("name", student.getName());
 
 if (student.getAge() < 10)
  throw new SpringException("Given age is too low");
 else
  model.addAttribute("age", student.getAge());

  model.addAttribute("id", student.getId());
  return "result";
}
.
.
.

If there are multiple exception handler methods defined, then handler method that is closest to the Exception class is used. For example, if we have two handler methods defined for IOException and Exception and our request handler method throws IOException, then the handler method for IOException will get executed.

2.Global Exception Handler-The handler methods in Global Controller Advice is same as Controller based exception handler methods and used when controller class is not able to handle the exception.@ControllerAdvice is a annotation provided by Spring allowing you to write global code that can be applied to a wide range of controllers, varying from all controllers to a chosen package or even a specific annotation. The annotation could be applied at Package Level, Class Level and at Annotation Level.

Package Level Application

@ControllerAdvice("my.chosen.package")
@ControllerAdvice(value = "my.chosen.package")
@ControllerAdvice(basePackages = "my.chosen.package")

Package Level Application – This will apply across all the classes inside the package where MyClass.class is placed.

@ControllerAdvice(basePackageClasses = MyClass.class)

Controller Level
Controller advice can be limited to certain controllers (not methods) by using one of the values of the @ControllerAdvice annotation, e.g.

@ControllerAdvice(assignableTypes = {MyController1.class, MyController2.class})

Controller identified by Annotation
If you want to apply it to controllers with certain annotations. The below snippet would only assist controllers annotated with @RestController (which it covers by default) but will not include @Controller annotated classes.

@ControllerAdvice(annotations = RestController.class)

3.HandlerExceptionResolver – can be implemented by the application to resolve exceptions thrown during processing an HTTP request. The exception can be thrown by one of the application’s handler methods or outside of it but during processing a request. The method, HandlerExceptionResolver#resolveException(), returns an instance of ModelAndView specifying an error page. The Implementations are typically registered as beans in the application context. The application registered HandlerExceptionResolvers will only be invoked if the exception is not already handled by the default HandlerExceptionResolvers. We can, however, change the order of the resolvers so that a given resolver can be invoked first.

@ExceptionHandler vs HandlerExceptionResolver vs @ControllerAdvice
@ExceptionHandler works at the Controller level and it is only active for that particular Controller, not globally for the entire application.

@ControllerAdvice used for global error handling in the Spring MVC application.It also has full control over the body of the response and the status code.

HandlerExceptionResolver-This will resolve any exception thrown by the application. It is used to resolve standard Spring exceptions to their corresponding HTTP Status Codes. It does not have control over the body of the response, means it does not set anything to the body of the Response.It does map the status code on the response but the body is null.

Posted in MVC.

A Bean definition contains the following piece of information called configuration metadata, which helps the container know the following things.

• The way a bean should be created.
• Life cycle details of a bean.
• Associated Bean dependencies.

The above metadata for the bean configuration is provided as a set of properties or attributes in an XML file (configuration file) which together prepare a bean definition. The following are the set of properties.

Properties Usage
class In a bean definition, it is a mandatory attribute. It is used to specify the bean class which can be used by the container to create the bean.
name In a bean definition, this attribute is used to specify the bean identifier uniquely. In XML based configuration metadata for a bean, we use the id and/or name attributes in order to specify the bean identifier(s).
scope This attribute is used to specify the scope of the objects which are created from a particular bean definition.
constructor-arg In a bean definition, this attribute is used to inject the dependencies.
properties In a bean definition, this attribute is used to inject the dependencies.
autowiring mode In a bean definition, this attribute is used to inject the dependencies.
lazy-initialization mode In a bean definition, a lazy-initialized bean informs the IoC container to create a bean instance only when it is first requested, instead of startup.
initialization method In a bean definition, a callback to be called after all required properties on the bean have been set up by the container.
destruction method In a bean definition, a callback to be used when the container that contains the bean is destroyed.

In the following example, we are going to look into an XML based configuration file which has different bean definitions. The definitions include lazy initialization (lazy-init), initialization method (init-method), and destruction method (destroy-method) as shown below. This configuration metadata file can be loaded either through BeanFactory or ApplicationContext

<?xml version = "1.0" encoding = "UTF-8"?>

<beans xmlns = "http://www.springframework.org/schema/beans"
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation = "http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

   <!-- A simple bean definition -->
   <bean id = "..." class = "...">
      <!— Here will be collaborators and configuration for this bean -->
   </bean>

   <!-- A bean definition which has lazy init set on -->
   <bean id = "..." class = "..." lazy-init = "true">
      <!-- Here will be collaborators and configuration for this bean -->
   </bean>

   <!-- A bean definition which has initialization method -->
   <bean id = "..." class = "..." init-method = "...">
      <!-- Here will be collaborators and configuration for this bean -->
   </bean>

   <!-- A bean definition which has destruction method -->
   <bean id = "..." class = "..." destroy-method = "...">
      <!-- collaborators and configuration for this bean go here -->
   </bean>

   <!-- more bean definitions can be written below -->
   
</beans>

Q1.What is the Difference between applicationContext and BeanFactory?
ApplicationContext is more feature rich container implementation and should be favored over BeanFactory.Both BeanFactory and ApplicationContext provides a way to get a bean from Spring IOC container by calling getBean(“bean name”)

  1. Bean factory instantiate bean when you call getBean() method while ApplicationContext instantiates Singleton bean when the container is started, It doesn’t wait for getBean to be called.
  2. BeanFactory provides basic IOC and DI features while ApplicationContext provides advanced features
  3. ApplicationContext is ability to publish event to beans that are registered as listener.
  4. implementation of BeanFactory interface is XMLBeanFactory while one of the popular implementation of ApplicationContext interface is ClassPathXmlApplicationContext.In web application we use we use WebApplicationContext which extends ApplicationContext interface and adds getServletContext method
  5. ApplicationContext provides Bean instantiation/wiring,Automatic BeanPostProcessor registration, Automatic BeanFactoryPostProcessor registration,Convenient MessageSource access and ApplicationEvent publication whereas BeanFactory provides only Bean instantiation/wiring

null

Q2.What is the Difference between Component and Bean?

  1. @Component auto detects and configures the beans using classpath scanning whereas @Bean explicitly declares a single bean, rather than letting Spring do it automatically.
  2. @Component does not decouple the declaration of the bean from the class definition where as @Bean decouples the declaration of the bean from the class definition.
  3. @Component is a class level annotation where as @Bean is a method level annotation and name of the method serves as the bean name.
  4. @Component need not to be used with the @Configuration annotation where as @Bean annotation has to be used within the class which is annotated with @Configuration.
  5. We cannot create a bean of a class using @Component, if the class is outside spring container whereas we can create a bean of a class using @Bean even if the class is present outside the spring container.
  6. @Component has different specializations like @Controller, @Repository and @Service whereas @Bean has no specializations.

@Component (and @Service and @Repository) are used to auto-detect and auto-configure beans using classpath scanning. There’s an implicit one-to-one mapping between the annotated class and the bean (i.e. one bean per class). Control of wiring is quite limited with this approach since it’s purely declarative.

@Bean is used to explicitly declare a single bean, rather than letting Spring do it automatically as above. It decouples the declaration of the bean from the class definition and lets you create and configure beans exactly how you choose.

Let’s imagine that you want to wire components from 3rd-party libraries (you don’t have the source code so you can’t annotate its classes with @Component), where an automatic configuration is not possible.The @Bean annotation returns an object that spring should register as a bean in the application context. The body of the method bears the logic responsible for creating the instance.
@Bean is applicable to methods, whereas @Component is applicable to types

Q3.What is the difference between @Configuration and @Component in Spring?
@Configuration Indicates that a class declares one or more @Bean methods and may be processed by the Spring container to generate bean definitions and service requests for those beans at runtime

@Component Indicates that an annotated class is a “component”. Such classes are considered as candidates for auto-detection when using annotation-based configuration and classpath scanning.

@Configuration is meta-annotated with @Component, therefore @Configuration classes are candidates for component scanning

Q4.Life cycle of Spring Bean

  1. There are five methods called before bean comes to ready state
  2. BeanPostProcessor method – postProcessBeforeInitilaization and postProcessAfterInitilaization would be called between init method(3 methods)
  3. After postProcessBeforeInitilaization @postContruct and afterPropertiesSet method would be called(2 methods)
  4. Bean comes to Ready state
  5. Once Spring shutdown is called @PreDestroy, destroy() and custom destroy method are called(3 methods)

Refer here

Q5.What is CGLIB in Spring?
Classes in Java are loaded dynamically at runtime. Cglib is using this feature of Java language to make it possible to add new classes to an already running Java program.Hibernate uses cglib for generation of dynamic proxies. For example, it will not return full object stored in a database but it will return an instrumented version of stored class that lazily loads values from the database on demand.Popular mocking frameworks, like Mockito, use cglib for mocking methods. The mock is an instrumented class where methods are replaced by empty implementations.

Q6.What is the difference between applicationcontext and webapplicationcontext in Spring?

  1. Spring MVC has ApplicationContext and WebApplicationContexts which is the extension of ApplicationContext
  2. There could be more than one WebApplicationContext
  3. All the Stateless attributes like DBConnections and Spring Security would be defined in ApplicationContext and shared among multiple WebApplicationContext
  4. ApplicationContext are loaded by ContextLoaderListener which is declared in web.xml
  5. A single web application can have multiple WebApplicationContext and each Dispatcher servlet (which is the front controller of Spring MVC architecture) is associated with a WebApplicationContext. The webApplicationContext configuration file *-servlet.xml is specific to a DispatcherServlet. And since a web application can have more than one dispatcher servlet configured to serve multiple requests, there can be more than one webApplicationContext file per web application.

Refer here

Q7.What are different bean scopes with realtime example?
Singleton: It returns a single bean instance per Spring IoC container.This single instance is stored in a cache of such singleton beans, and all subsequent requests and references for that named bean return the cached object. If no bean scope is specified in the configuration file, singleton is default. Real world example: connection to a database

Prototype: It returns a new bean instance each time it is requested. It does not store any cache version like singleton. Real world example: declare configured form elements (a textbox configured to validate names, e-mail addresses for example) and get “living” instances of them for every form being created.Batch processing of data involves prototype scope beans.

Request: It returns a single bean instance per HTTP request. Real world example: information that should only be valid on one page like the result of a search or the confirmation of an order. The bean will be valid until the page is reloaded.

Session: It returns a single bean instance per HTTP session (User level session). Real world example: to hold authentication information getting invalidated when the session is closed (by timeout or logout). You can store other user information that you don’t want to reload with every request here as well.

GlobalSession: It returns a single bean instance per global HTTP session. It is only valid in the context of a web-aware Spring ApplicationContext (Application level session). It is similar to the Session scope and really only makes sense in the context of portlet-based web applications. The portlet specification defines the notion of a global Session that is shared among all of the various portlets that make up a single portlet web application. Beans defined at the global session scope are bound to the lifetime of the global portlet Session.

Q8.What is Portlet application?what is the difference between a portlet and a servlet?
Servlets and Portlets are web based components which use Java for their implementation.Portlets are managed by a portlet container just like servlet is managed by servlet container.
When your application works in Portlet container it is built of some amount of portlets. Each portlet has its own session, but if your want to store variables global for all portlets in your application than you should store them in globalSession. This scope doesn’t have any special effect different from session scope in Servlet based applications.

The simplest way to think of this is that a servlet renders an entire web page, and a portlet renders a specific rectangular part (subsection) of a web page. For example, the advertising bar on the right hand side of a news page could be rendered as a portlet. But you wouldn’t implement a single edit field as a portlet, because that’s too granular. Basically if you break down a web page into it’s major sectional areas, those are good candidates to make into portlets. Portlet never renders complete web page with html start and end tags but part of page.

Spring Bean life Cycle is hooked to the below 4 interfaces Methods

  1. InitializingBean and DisposableBean callback interfaces
  2. *Aware interfaces for specific behavior
  3. Custom init() and destroy() methods in bean configuration file
  4. @PostConstruct and @PreDestroy annotations

null

InitializingBean and DisposableBean callback interfaces
InitializingBean and DisposableBean are two marker interfaces, a useful way for Spring to perform certain actions upon bean initialization and destruction.

  1. For bean implemented InitializingBean, it will run afterPropertiesSet() after all bean properties have been set.
  2. For bean implemented DisposableBean, it will run destroy() after Spring container is released the bean.

Refer Here and here

Custom init() and destroy() methods in bean configuration file
Using init-method and destroy-method as attribute in bean configuration file for bean to perform certain actions upon initialization and destruction.

@PostConstruct and @PreDestroy annotations
We can manage lifecycle of a bean by using method-level annotations @PostConstruct and @PreDestroy.

The @PostConstruct annotation is used on a method that needs to be executed after dependency injection is done to perform any initialization.

The @PreDestroy annotation is used on methods as a callback notification to signal that the instance is in the process of being removed by the container.

@PostConstruct vs init-method vs afterPropertiesSet
There is any difference but there are priorities in the way they work. @PostConstruct, init-method.@PostConstruct is a JSR-250 annotation while init-method is Spring’s way of having an initializing method.If you have a @PostConstruct method, this will be called first before the initializing methods are called. If your bean implements InitializingBean and overrides afterPropertiesSet, first @PostConstruct is called, then the afterPropertiesSet and then init-method.

@Component
public class MyComponent implements InitializingBean {
	
	@Value("${mycomponent.value:Magic}")
	public String value;
	
	public MyComponent() {
		log.info("MyComponent in constructor: [{}]", value); // (0) displays: Null [properties not set yet]
	}
	
	@PostConstruct
	public void postConstruct() {
		log.info("MyComponent in postConstruct: [{}]", value); // (1) displays: Magic
	}

	@Override // (equivalent to init-method in XML; overrides InitializingBean.afterPropertiesSet()
	public void afterPropertiesSet() {
		log.info("MyComponent in afterPropertiesSet: [{}]", value);  // (2) displays: Magic
	}	

        public void initIt() throws Exception {
	  log.info("MyComponent in init: " + value);
	}

	@PreDestroy
	public void preDestroy() {
		log.info("MyComponent in preDestroy: [{}], self=[{}]", value); // (3) displays: 
	}

        public void cleanUp() throws Exception {
	  log.info("Spring Container is destroy! Customer clean up");
	}
}

Spring.xml

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
	<bean id="customerService" class="com.mkyong.customer.services.CustomerService" 
		init-method="initIt" destroy-method="cleanUp">   		
		<property name="message" value="i'm property message" />
	</bean>		
</beans>

Output

MyComponent in constructor: [null]
MyComponent in postConstruct: [Magic]
MyComponent in init: [Magic from XML]
MyComponent in afterPropertiesSet: [Magic]
MyComponent in preDestroy: [Magic]
Spring Container is destroy! Customer clean up

When to use what?
init-method and destroy-method is the recommended approach because of no direct dependency to Spring Framework and we can create our own methods.
InitializingBean and DisposableBean To interact with the container’s management of the bean lifecycle, you can implement the Spring InitializingBean and DisposableBean interfaces. The container calls afterPropertiesSet() for the former and destroy() for the latter to allow the bean to perform certain actions upon initialization and destruction of your beans.
@PostConstruct and @PreDestroy – The JSR-250 @PostConstruct and @PreDestroy annotations are generally considered best practice for receiving lifecycle callbacks in a modern Spring application. Using these annotations means that your beans are not coupled to Spring specific interfaces.

What are different ways to create Bean in Spring Boot?

  1. Using @Component over class – To create app specific bean
  2. Using @Configuration over class and @Bean over method – To create bean from third party class added as JAR dependency. You cannot add component in added JAR class files.

What is Dependency Injection?
Dependency injection is basically providing the objects that an object needs (its dependencies) instead of having it construct them itself.

What are Types of Dependency Injection?

  1. Constructor Injection – Dependency provided as parameter to constructor. This ensures Object is fully initialized upon creation and promoting immutability
  2. Setter Injection – Setter injection is having independent setter for each class attributes and calling setter method while initializing. Setter Injection allow more flexibility by allowing dependencies to be set or changed after object creation.
  3. Field Injection – Field injection is old method of injecting dependencies by specifying the @Autowired over field name. It works based on Java reflection and it is not recommended as it makes code more difficult to test

What are Stereotype Annotations?

Stereotype – idea of a particular type of person or thing.

Spring comes with 4 Stereotype annotations as below.

@Component is a generic stereotype for any Spring-managed component. @Repository, @Service, @Controller are specializations of @Component for more specific use cases (in the persistence, service, and presentation layers, respectively).

  1. @Component general-purpose stereotype annotation indicating that the class is a spring component.
  2. @Controller @Controller annotation indicates that a particular class serves the role of a controller. The dispatcher scans the classes annotated with @Controller and detects methods annotated with @RequestMapping annotations within them. We can use @RequestMapping on/in only those methods whose classes are annotated with @Controller
  3. @Repository
  4. stereotype for persistence layer. @Repository’s job is to catch platform specific exceptions and re-throw them as one of Spring’s unified unchecked exception. By masking the platform specific exception to spring unified exception it helps 1.Providing higher level of Abstraction for User 2.By throwing unchecked exception it prevents user from adding unnecessary boiler plate for exception handling by means of try catch blocks

  5. @Service – @Service beans hold the business logic and call methods in the repository layer.

Note : Spring may add special functionalities for @Service, @Controller and @Repository based on their layering conventions.

How it is internally is all 3 are marked with @Component.@CompnentScan only scans @Component and does not look for @Controller, @Service and @Repository in general. They are scanned because they themselves are annotated with @Component.

@Component
public @interface Service {
    ….
}

@Component
public @interface Repository {
    ….
}

@Component
public @interface Controller {
    …
}

What happens when more than one bean of same type is found? What would be workaround?
Application would fail to start with error message Require Single bean but N beans found.

This could be addressed in two ways

  1. Using @Qualifier annotation
  2. Using @Primary annotation

@Qualifier annotation takes bean Id as value to uniquely identify a bean.

StudentController.java

public class StudentController{
 .
 @Autowired
 public StudentController(@Qualifier("student") Person person){
 .
 }
}

Student.java

@Component
public class Student implements Person{
.
}

@Primary annotation works by giving first preference to bean which is marked with @Primary annotation. If two beans are marked with @Primary annotation then Spring boot throws an error. If both @Primary and @Qualifier annotation is used, then @Qualifier annotation takes preference.

@Primary vs @Qualifier Which one takes precedence?
@Qualifier takes precedence over @Primary annotation.

What does @Lazy annotation do?
Unlike the bean which are marked with @Component are loaded at startup when the app start, @Lazy annotation does the bean loading only when it is needed.

This can be Configured globally as well by specifying in application.properties as below. If your application has lot of components and because of this the app takes long time to start then its better to use this.

application.properties

spring.main.lazy-initialization=true

Note: If you use @Lazy annotation along with @Restcontroller it may lead to timeout issues.

Report.java

public interface Report {
    String generateReport();
}

PDFReport.java

@Primary
@Component
public class PDFReport implements Report{
    public PDFReport() {
        System.out.println("Loaded PDFReport");
    }

    @Override
    public String generateReport() {
        return "PDF Report";
    }
}

excelReport.java

@Component
public class excelReport implements Report{
    public excelReport() {
        System.out.println("Loading Excel Report");
    }

    @Override
    public String generateReport() {
        return "Excel Report";
    }
}

textReport.java

@Component
@Lazy
public class textReport implements Report{
    public textReport() {
        System.out.println("Loading textReport Report");
    }
    @Override
    public String generateReport() {
        return "Text Report";
    }
}

GenerateReport.java

@RestController
public class GenerateReport {
    private Report report;

    public GenerateReport(@Qualifier("excelReport") Report report){
        this.report = report;
    }

    @GetMapping("/generateReport")
    public String generateReport(){
        return "Printing report in "+ report.generateReport() + " format";
    }
}

Excel Report format would be printed as @Qualifier would take precedence
Output in Browser(http://localhost:8080/generateReport)

Loading Excel Report
Loaded PDFReport

Printing report in Excel Report format

What are different Bean Scopes?
Singleton – Only one bean for Container, served same bean for every access
Prototype – New bean for every access
Request – New bean for every request
Session – Only one bean for Session
Application – Only one bean for Application
Websocket

@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)

Checking Object based on Bean Scope – Singleton
excelReport bean with Singleton scope returning same bean every access
excelReport.java

@Component
public class excelReport implements Report{
.
.
}

GenerateReport.java

@RestController
public class GenerateReport {
    private Report report1;
    private Report report2;

    public GenerateReport(@Qualifier("excelReport") Report report1, @Qualifier("excelReport") Report report2){
        this.report1 = report1;
        this.report2 = report2;
    }

    @GetMapping("/checkBean")
    public String checkBean(){
        if(report1 == report2){
            return "Bean are Same";
        }else{
            return  "Bean are Different";
        }
    }
}

Output(http://localhost:8080/checkBean)

Bean are Same

Checking Object based on Bean Scope – Prototype
pdfReport bean with Prototype scope returning different bean on every access
PDFReport.java

@Primary
@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class PDFReport implements Report{
  .
  .
}

GenerateReport.java

@RestController
public class GenerateReport {
    private Report report1;
    private Report report2;

    public GenerateReport(Report report1, Report report2){
        this.report1 = report1;
        this.report2 = report2;
    }

    @GetMapping("/checkBean")
    public String checkBean(){
        if(report1 == report2){
            return "Bean are Same";
        }else{
            return  "Bean are Different";
        }
    }
}

Output(http://localhost:8080/checkBean)

Bean are Different

How to inject bean created using new Operator or Injecting Spring beans into non-managed objects
Objects for 3rd party JAR are created using @Configuration at class level and using @Bean at method level. This is one other way to create bean other than @Component as
we wont be able to change the source of 3rd party class files.

  1. Using @Configuration and @Bean annotation
  2. Using @Configurable refer here
  3. using AutowireCapableBeanFactory

Let take the below code

public class MyBean 
{
    @Autowired 
    private AnotherBean anotherBean;
}

MyBean obj = new MyBean();

I have a class doStuff in which the obj of MyBean created using new operator needs to be injected. To do this use AutowireCapableBeanFactory and call autowireBean method with beanFactory reference.

private @Autowired AutowireCapableBeanFactory beanFactory;

public void doStuff() {
   MyBean obj = new MyBean();
   beanFactory.autowireBean(obj);
   //obj will now have its dependencies autowired.
}

What is the Difference between @Inject and @Autowired in Spring Framework?
@Inject specified in javax.inject.Inject annotations is part of the Java CDI (Contexts and Dependency Injection) standard introduced in Java EE 6 (JSR-299). Spring has chosen to support using @Inject synonymously with their own @Autowired annotation.@Autowired is Spring’s own (legacy) annotation. @Inject is part of a new Java technology called CDI that defines a standard for dependency injection similar to Spring. In a Spring application, the two annotations work the same way as Spring has decided to support some JSR-299 annotations in addition to their own.

Use of the Following in Spring Framework?
@RequestMapping – All incoming requests are handled by the Dispatcher Servlet and it routes them through the Spring framework. When the Dispatcher Servlet receives a web request, it determines which controllers should handle the incoming request. Dispatcher Servlet initially scans all the classes that are annotated with the @Controller annotation. The dispatching process depends on the various @RequestMapping annotations declared in a controller class and its handler methods.The @RequestMapping annotation is used to map the web request onto a handler class (i.e. Controller) or a handler method and it can be used at the Method Level or the Class Level.

Example – for the URL http://localhost:8080/ProjectName/countryController/countries

@Controller
@RequestMapping(value = "/countryController")
public class CountryController {
 
 @RequestMapping(value = "/countries", method = RequestMethod.GET, headers = "Accept=application/json")
 public List getCountries() {
    // Some Business Logic
 } 
Annotations Equivalent
@GetMapping @RequestMapping(method = RequestMethod.GET)
@PostMapping @RequestMapping(method = RequestMethod.POST)
@PutMapping @RequestMapping(method = RequestMethod.PUT)
@DeleteMapping @RequestMapping(method = RequestMethod.DELETE)
@PatchMapping @RequestMapping(method = RequestMethod.PATCH)

@RequestParam – By using RequestParam we can get parameters to the method

@RequestMapping(value = "/display", method = RequestMethod.GET)
public String showEmployeeForm(@RequestParam("empId") String empId) {
        // Some Business Logic
}

@Pathvariable – @PathVariable is to obtain some placeholder from the URI
If empId and empName as parameters to the method showEmployeeForm() by using the @PathVariable annotation. For e.g.: /employee/display/101/Mux
empId = 101
empName = Mux

@Controller
@RequestMapping(value = "/employee")
public class EmployeeController {
    @RequestMapping(value = "/display/{empId}/{empName}")
    public ModelAndView showEmployeeForm(@PathVariable String empId, @PathVariable String empName) {
                // Some Business Logic
    } 
}

What is the Difference between @RequestParam vs @PathVariable?
@RequestParam annotation has following attributes

http://localhost:8080/springmvc/hello/101?param1=10¶m2=20
public String getDetails(
    @RequestParam(value="param1", required=true) String strParam1,
        @RequestParam(value="param2", required=false,  defaultValue = "John") String strParam2){
...
}

@PathVariable is always considered required and cannot be null whereas @RequestParam could be null

@RequestParam annotation can specify default values if a query parameter is not present or empty by using a default Value attribute, provided the required attribute is false. . If a corresponding path segment is missing, Spring will result in a 404 Not Found error.

defaultValue This is the default value as a fallback mechanism if request is not having the value or it is empty. i.e param1
name Name of the parameter to bind i.e param1
required Whether the parameter is mandatory or not. If it is true, failing to send that parameter will fail. i.e false
value This is an alias for the name attribute i.e param1

@PathVariable is to obtain some placeholder from the URI (Spring call it an URI Template) and @RequestParam is to obtain an parameter from the URI as well.@PathVariable annotation has only one attribute value for binding the request URI template. It is allowed to use the multiple @PathVariable annotation in the single method. But, ensure that no more than one method has the same pattern.Annotation which indicates that a method parameter should be bound to a name-value pair within a path segment. Supported for RequestMapping annotated handler methods.

localhost:8080/person/Tom;age=25;height=175 and Controller:
@GetMapping("/person/{name}")
@ResponseBody
public String person(
    @PathVariable("name") String name, 
    @MatrixVariable("age") int age,
    @MatrixVariable("height") int height) {

    // ...
}

How Spring will decide bean if there are multiple implementation of Same Instance?

In such case it would fail at start telling expected 1 bean but found n bean

We can use @Qualifier annotation where we can decide the bean to be loaded based on the beanId. beanId is always the component name with camel casing

public class GenerateReport {
    private Report report1;
    private Report report2;

    public GenerateReport(@Qualifier("excelReport") Report report1, Report report2){
        this.report1 = report1;
        this.report2 = report2;
    }
}

What BeanLife cycle methods are available?

@PostConstruct and @PreDestroy

@Component
public class excelReport implements Report{
    public excelReport() {
        System.out.println("Loading Excel Report");
    }

    @Override
    public String generateReport() {
        return "Excel Report";
    }

    @PreDestroy
    public void doCleanUpStuff(){
        System.out.println("Disposing ExcelReport....: Prints when Server Stops");
    }

    @PostConstruct
    public void doStartUpStuff(){
        System.out.println("Completed Initialization ExcelReport...: Prints when Server Starts");
    }
}

Output – When Server Starts

Completed Initialization ExcelReport...: Prints when Server Starts

Output – When Server Stops

Disposing ExcelReport....: Prints when Server Stops

What is use of @RequestBody and @ResponseBody?

  1. @RequestBody and @ResponseBody used in controller to implement smart object serialization and deserialization. They help you avoid boilerplate code by extracting the logic of message conversion and making it an aspect. Other than that they help you support multiple formats for a single REST resource without duplication of code.
  2. If you annotate a method with @ResponseBody, spring will try to convert its return value and write it to the http response automatically.
  3. If you annotate a methods parameter with @RequestBody, spring will try to convert the content of the incoming request body to your parameter object on the fly.

What is @Transactional used for?
When Spring loads your bean definitions, and has been configured to look for @Transactional annotations, it will create these proxy objects around your actual bean. These proxy objects are instances of classes that are auto-generated at runtime. The default behaviour of these proxy objects when a method is invoked is just to invoke the same method on the “target” bean (i.e. your bean).
Refere here

@Configuration – @Configuration as a replacement to the XML based configuration for configuring spring beans.So instead of an xml file we write a class and annotate that with @Configuration and define the beans in it using @Bean annotation on the methods.It is just another way of configuration Indicates that a class declares one or more @Bean methods and may be processed by the Spring container to generate bean definitions and service requests for those beans at runtime.

Use @Configuration annotation on top of any class to declare that this class provides one or more @Bean methods and may be processed by the Spring container to generate bean definitions and service requests for those beans at runtime.

AppConfig.java

@Configuration
public class AppConfig {
 
    @Bean(name="demoService")
    public DemoClass service()
    {
        
    }
}

pom.xml
The following dependency should be added to pom.xml before using @configuration annotation to get the bean from the context

<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-context</artifactId>
		<version>5.0.6.RELEASE</version>
</dependency>
public class VerifySpringCoreFeature
{
    public static void main(String[] args)
    {
        ApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfiguration.class); 
        DemoManager  obj = (DemoManager) context.getBean("demoService"); 
        System.out.println( obj.getServiceName() );
    }
}

What if I want to ensure the beans are already loaded even before requested and fail-fast

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MySpringApp {
	public static void main(String[] args) {
		AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
		ctx.register(MyConfiguration.class);
		ctx.refresh();
		MyBean mb1 = ctx.getBean(MyBean.class);
		MyBean mb2 = ctx.getBean(MyBean.class);
		ctx.close();
	}
}

In the above example Spring loads beans into it’s context before we have even requested it. This is to make sure all the beans are properly configured and application fail-fast if something goes wrong.

Now what will happen if we uncomment the @Configuration annotation in the above class. In this case, if we make a call to myBean() method then it will be a plain java method call and we will get a new instance of MyBean and it won’t remain singleton.

@Configurble – How to inject dependencies into objects that are not created by Spring

public class CarSalon {
    //...
    public void testDrive() {
        Car car = new Car();
        car.startCar();
    }
}
 
@Component
public class Car {
    @Autowired
    private Engine engine;
    @Autowired
    private Transmission transmission;
 
    public void startCar() {
        transmission.setGear(1);
        engine.engineOn();
        System.out.println("Car started");
    }
}
 
@Component
public class Engine {
//...
}
 
@Component
public class Transmission {
//...
}

In the above example

  1. We try to create a Object for Car class using new operator
  2. How ever objects created using new operator are not container managed rather Java Runtime Managed
  3. Trying to access the startCar method using car object will throw NullPointerException
  4. However using @Configurable annotation will tell Spring to inject dependencies into the object before the constructor is run
  5. You need to have these JAR files in pom.xml inorder to make it work.aspectj-x.x.x.jar, aspectjrt.jar, aspectjveawer-x.x.x.jar
@Configurable(preConstruction = true)
@Component
public class Car {
 
    @Autowired
    private Engine engine;
    @Autowired
    private Transmission transmission;
 
    public void startCar() {
        transmission.setGear(1);
        engine.engineOn();
 
        System.out.println("Car started");
    }
}

Spring Version 4

  1. Spring Framework 4.0 provides support for several Java 8 features
  2. Java EE version 6 or above with the JPA 2.0 and Servlet 3.0 specifications
  3. Groovy Bean Definition DSL- external bean configuration using a Groovy DSL
  4. Core Container Improvements
    1. The @Lazy annotation can now be used on injection points, as well as on @Bean definitions.
    2. The @Description annotation has been introduced for developers using Java-based configuration
    3. Using generics as autowiring qualifiers
    4. Beans can now be ordered when they are autowired into lists and arrays. Both the @Order annotation and Ordered interface are supported.
    5. A generalized model for conditionally filtering beans has been added via the @Conditional annotation

Spring Version 5

  1. Functional programming with Kotlin
  2. Reactive Programming Model.The Reactive Streams API is officially part of Java 9. In Java 8, you will need to include a dependency for the Reactive Streams API specification.
  3. @Nullable and @NotNull annotations will explicitly mark nullable arguments and return values. This enables dealing null values at compile time rather than throwing NullPointerExceptions at runtime.
  4. Spring Framework 5.0 now supports candidate component index as an alternative to classpath scanning..Reading entities from the index rather than scanning the classpath.Loading the component index is cheap. Therefore the startup time with the index remains constant as the number of classes increase. While for a compoent scan the startup time increases significantly.
  5. requires Java 8 as a minimum JDK version.Spring 5 is fully compatible with Java 9.
  6. Servlet 3.1,JMS 2.0,JPA 2.1,Hibernate5,JAX-RS 2.0,Bean Validation 1.1,JUnit 5
  1. Spring sits between the application classes and the O/R mapping tool, undertakes transactions, and manages connection objects.It translates the underlying persistence exceptions thrown by Hibernate to meaningful, unchecked exceptions of type DataAccessException. Moreover, Spring provides IoC and AOP, which can be used in the persistence layer
  2. Hibernate uses Template Pattern – To clean the code and provide more manageable code, Spring utilizes a pattern called Template Pattern. By this pattern, a template object wraps all of the boilerplate repetitive code. Then, this object delegates the persistence calls as a part of functionality in the template. In the Hibernate case, HibernateTemplate extracts all of the boilerplate code, such as obtaining a Session, performing transaction, and handing exceptions.
  3. With Spring, the HibernateTemplate object interacts with Hibernate. This object removes the boilerplate code from DAO implementations.Any invocation of one of HibernateTemplate’s methods throws the generic DataAccessException exception instead of HibernateException (a Hibernate-specific exception).Spring lets us demarcate transactions declaratively, instead of implementing duplicated transaction-management code.
  4. The HibernateTemplate class uses a SessionFactory instance internally to obtain Session objects for Hibernate interaction. Interestingly, you can configure the SessionFactory object via the Spring IoC container to be instantiated and injected into DAO objects.
  5. Spring provides its own exception hierarchy, which sits on the exception hierarchies of the O/R mapping tools.The Spring exception hierarchy is defined as a subclass of org.springframework.dao.DataAccessException. Spring catches any exception thrown in the underlying persistence technology and wraps it in a DataAccessException instance.The DataAccessException object is an unchecked exception, because it extends RuntimeException and you do not need to catch it if you do not want to.
  6. Spring provides distinct DAO base classes for the different data-access technologies it supports. When you use Hibernate with Spring, the DAO classes extend the Spring org.springframework.orm.hibernate3.support.HibernateDaoSupport class. This class wraps an instance of org.springframework.orm.hibernate3.HibernateTemplate, which in turn wraps an org.hibernate.SessionFactory instance.
    org.springframework.orm.hibernate3.support.HibernateDaoSupport   
                              |
       org.springframework.orm.hibernate3.HibernateTemplate
                              |
                 org.hibernate.SessionFactory   
      
  7. HibernateException is thrown for any failure when directly interacting with Hibernate. When Spring is used, HibernateException is caught by Spring and translated to DataAccessException for any persistence failure. Both exceptions are unchecked, so you do not need to catch them if you don’t want to do.
  8. DAO Implementation using DAOSupport
    StudentDao.java

    import java.util.Collection;
    
    public interface StudentDao 
    {
      public Student getStudent(long id);
      public Collection getAllStudents();
      public Collection findStudents(String lastName);
      public void saveStudent(Student std);
      public void removeStudent(Student std);
    }
    

    Using DAOSupport Object
    StudentDao.java

    import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
    import java.util.Collection;
    
    public class HibernateStudentDao extends HibernateDaoSupport implements StudentDao 
    {
      public Student getStudent(long id) 
      {
        return (Student) getHibernateTemplate().get(Student.class, new Long(id));
      }
    
      public Collection getAllStudents()
      {
        return getHibernateTemplate().find("from Student std order by std.lastName, std.firstName");
      }
    
    
      public Collection findStudents(String lastName) 
      {
        return getHibernateTemplate().find("from Student std where std.lastName like ?", lastName + "%");
      }
    
      public void saveStudent(Student std) 
      {
        getHibernateTemplate().saveOrUpdate(std);
      }
    
      public void removeStudent(Student std) 
      {
        getHibernateTemplate().delete(std);
      }
    }
    
  9. all of the persistent methods in the DAO class use the getHibernateTemplate() method to access the HibernateTemplate object.
  10. HibernateTemplate is a Spring convenience class that delegates DAO calls to the Hibernate Session API. This class exposes all of Hibernate’s Session methods, as well as a variety of other convenient methods that DAO classes may need. Because HibernateTemplate convenient methods are not exposed by the Session interface, you can use find() and findByCriteria() when you want to execute HQL or create a Criteria object.
  11. Using the HibernateDaoSupport class as the base class for all Hibernate DAO implementations would be more convenient, but you can ignore this class and work directly with a HibernateTemplate instance in DAO classes. To do so, define a property of HibernateTemplate in the DAO class, which is initialized and set up via the Spring IoC container.
  12. DAO Implementation Using HibernateTemplate

    import org.springframework.orm.hibernate3.HibernateTemplate;
    import java.util.Collection;
    
    public class HibernateStudentDao implements StudentDao 
    {
        
      HibernateTemplate hibernateTemplate;
    
      public Student getStudent(long id) 
      {
        return (Student) getHibernateTemplate().get(Student.class, new Long(id));
      }
    
      public Collection getAllStudents()
      {
        return getHibernateTemplate().find("from Student std order by std.lastName, std.firstName");
      }
    
      public Collection findStudents(String lastName) 
      {
        return getHibernateTemplate().find("from Student std where std.lastName like "+ lastName + "%");
      }
    
      public void saveStudent(Student std) 
      {
        getHibernateTemplate().saveOrUpdate(std);
      }
    
      public void removeStudent(Student std) 
      {
        getHibernateTemplate().delete(std);
      }
    
      public HibernateTemplate getHibernateTemplate() 
      {
        return hibernateTemplate;
      }
    
      public void setHibernateTemplate(HibernateTemplate hibernateTemplate) 
      {
        this.hibernateTemplate = hibernateTemplate;
      }
    }
     
  13. The DAO class now has the setHibernateTemplate() method to allow Spring to inject the configured HibernateTemplate instance into the DAO object.Moreover, the DAO class can abandon the HibernateTemplate class and use the SessionFactory instance directly to interact with Hibernate.

    Using SessionFactory Object

    import org.hibernate.HibernateException;
    import org.hibernate.Session;
    import org.hibernate.Query;
    import org.hibernate.SessionFactory;
    import org.springframework.orm.hibernate3.SessionFactoryUtils;
    
    import java.util.Collection;
    
    public class HibernateStudentDao implements StudentDao 
    {
      SessionFactory sessionFactory;
    
      public Student getStudent(long id) 
      {
        Session session = SessionFactoryUtils.getSession(this.sessionFactory, true);
        try {
          return (Student) session.get(Student.class, new Long(id));
        } catch (HibernateException ex) {
          throw SessionFactoryUtils.convertHibernateAccessException(ex);
        } finally {
          SessionFactoryUtils.closeSession(session);
        }
      }
    
      public Collection getAllStudents()
      {
        Session session = SessionFactoryUtils.getSession(this.sessionFactory, true);
        try {      
          Query query = session.createQuery("from Student std order by std.lastName, std.firstName");
          Collection allStudents = query.list();
          return allStudents;
        } catch (HibernateException ex) {
          throw SessionFactoryUtils.convertHibernateAccessException(ex);
        } finally {
          SessionFactoryUtils.closeSession(session);
        }
      }
    
      public Collection getGraduatedStudents()
      {
        Session session = SessionFactoryUtils.getSession(this.sessionFactory, true);
        try {
          Query query = session.createQuery("from Student std where std.status=1");
          Collection graduatedStudents = query.list();
          return graduatedStudents;
        } catch (HibernateException ex) {
          throw SessionFactoryUtils.convertHibernateAccessException(ex);
        } finally {
          SessionFactoryUtils.closeSession(session);
        }
      }
    
      public Collection findStudents(String lastName) 
      {
        Session session = SessionFactoryUtils.getSession(this.sessionFactory, true);
        try {
          Query query = session.createQuery("from Student std where std.lastName like ?");
          query.setString(1, lastName + "%");
          Collection students = query.list();
          return students;
        } catch (HibernateException ex) {
          throw SessionFactoryUtils.convertHibernateAccessException(ex);
        } finally {
          SessionFactoryUtils.closeSession(session);
        }
      }
    
      public void saveStudent(Student std) 
      {
        Session session = SessionFactoryUtils.getSession(this.sessionFactory, true);
        try {
          session.save(std);
        } catch (HibernateException ex) {
          throw SessionFactoryUtils.convertHibernateAccessException(ex);
        } finally {
          SessionFactoryUtils.closeSession(session);
        }
      }
    
      public void removeStudent(Student std) 
      {
        Session session = SessionFactoryUtils.getSession(this.sessionFactory, true);
        try {
          session.delete(std);
        } catch (HibernateException ex) {
          throw SessionFactoryUtils.convertHibernateAccessException(ex);
        } finally {
          SessionFactoryUtils.closeSession(session);
        }
      }
    
      public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
      }
    }
    
  14. In all of the methods above, the SessionFactoryUtils class is used to obtain a Session object. The provided Session object is then used to perform the persistence operation. SessionFactoryUtils is also used to translate HibernateException to DataAccessException in the catch blocks and close the Session objects in the final blocks. Note that this DAO implementation bypasses the advantages of HibernateDaoSupport and HibernateTemplate. You must manage Hibernate’s Session manually (as well as exception translation and transaction management) and implement much boilerplate code.
  15. org.springframework.orm.hibernate3.SessionFactoryUtils is a Spring helper class for obtaining Session, reusing Session within transactions, and translating HibernateException to the generic DataAccessException.
  16. In cases where you need to work directly with Session objects, you can use an implementation of the org.springframework.orm.hibernate3.HibernateCallback interface as the handler to work with Sessions.
  17. An implicit implementation of HibernateCallback is created and its only doInHibernate() method is implemented. The doInHibernate() method takes an object of Session and returns the result of persistence operation, null if none. The HibernateCallback object is then passed to the execute() method of HibernateTemplate to be executed. The doInHibernate() method just provides a handler to work directly with Session objects that are obtained and used behind the scenes.

    Using HibernateCallback

     public void saveStudent(Student std) 
     {
      HibernateCallback callback = new HibernateCallback() {
       public Object doInHibernate(Session session) throws 
    HibernateException, SQLException {
        return session.saveOrUpdate(std);
       }
      };
      getHibernateTemplate().execute(callback);  
     }
     

What is BeanFactory?
The BeanFactory is the actual container which instantiates, configures, and manages a number of beans.Let have a look at how spring works

How it Works

  1. When the application is Deployed the Spring framework reads the xml file and creates the objects.Those are the objects which you see in the Spring Container
  2. Now when you try to refer any of these objects from the outside object using the new method it will throw an exception since or when you try to create a object using new method, the spring container has no idea about the object which you are trying to access
  3. Now to access the object in the container you will use the BeanFactory Objects

BeanFactory is represented by org.springframework.beans.factory.BeanFactory interface.It is the main and the basic way to access the Spring container.Other ways to access the spring container such as ApplicationContext,ListableBeanFactory, ConfigurableBeanFactory etc. are built upon this BeanFactory interface.

BeanFactory interface defines basic functionality for the Spring Container like

  1. It is built upon Factory Design Pattern
  2. provides DI / IOC mechanism for the Spring.
  3. It loads the beans definitions and their property descriptions from some configuration source (for example, from XML configuration file) .
  4. Instantiates the beans when they are requested like beanfactory_obj.getBean(“beanId”).
  5. Wire dependencies and properties for the beans according to their configuration defined in configuration source while instantiating the beans.
  6. Manage the bean life cycle by bean lifecycle interfaces and calling initialization and destruction methods.

Note that BeanFactory does not create the objects of beans immediately when it loads the configuration for beans from configuration source.Only bean definitions and their property descriptions are loaded. Beans themselves are instantiated and their properties are set only when they are requested such as by getBean() method.

Different BeanFactory Implementations:

XmlBeanFactory using Constructor:

Resource res = new FileSystemResource("c:/beansconfig.xml");
BeanFactory bfObj = new XmlBeanFactory(res);
MyBean beanObj= (MyBean) bfObj.getBean("mybean");
  1. The XmlBeanFactory takes the resource object as Parameter
  2. bfObj points to the Spring Container from which you try to fetch the object
  3. mybean is the ID of the Object specified in the XML File
  4. In the above case BeanFactory loads the beans lazily.BeanFactory will read bean definition of a bean with id “mybean” from beansconfig.xml file, instantiates it and return a reference to that.
  5. There are tow implementation of Resource Intefrace. one is org.springframework.core.io.FileSystemResource as seen above and other is org.springframework.core.io.ClassPathResource which loads Loads the resource from classpath(shown below).
ClassPathResource resorce = new ClassPathResource ("beansconfig.xml");
BeanFactory factory = new XmlBeanFactory(resource);

ClassPathXmlApplicationContext:

ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(
        new String[] {"applicationContext.xml", "applicationContext-part2.xml"});

//an ApplicationContext is also a BeanFactory.
BeanFactory factory = (BeanFactory) appContext;

null

Note BeanFactory is not recomended for use in latest Spring versions. It is there only for backward compatability. ApplicationContext is preferred over this because ApplicationContext provides more advance level features which makes an application enterprise level application.