Showing posts with label Spring autowiring. Show all posts
Showing posts with label Spring autowiring. Show all posts

Friday, January 12, 2024

Autowiring in Spring Using XML Configuration

Spring framework provides an option to autowire the beans. In that case you don't need to explicitly wire the bean properties (using ref attribute) but Spring will do it automatically by using the "autowire" attribute.

In Spring you can autowire dependencies using XML configuration or use the annotations to autowire the dependencies. This post talks about autowiring in Spring using XML configuration.


Autowiring modes in Spring

Spring provides four kind of autowiring modes (updated as per Spring 4.x where autodetect option has been removed).

  • no- The traditional Spring default. No automagical wiring. Bean references must be defined in the XML file via the <ref/> element (or "ref" attribute). autowire=”default” is same as autowire=”no”

  • byName- Autowiring by name means properties of the autowired bean will be wired by searching for bean with same name/id in the configuration file. If such a bean is found it is injected, properties for which no matching bean is found will remain unwired which may later result in error.

  • byType- Autowiring by type means properties of the autowired bean will be wired by searching for bean whose type is compatible with the property's type. If such a bean is found it is injected, properties for which no matching bean is found will remain unwired which may later result in error.

  • constructor- In this case wiring will be done using the constructor of the autowired bean by looking for the bean whose type is compatible with the constructor argument.

  • autodetect- In case of autodetect auto wiring using constructor will be tried first, if default constructor only is there and autowiring using constructor can't be done then autowiring byType is used. Note that this option was available till Spring 3.x (deprecated) or older versions. In Spring 4.x it is removed and this option is not available anymore. In this post autodetect example is not there.

Autowiring in Spring - XML configuration

First thing to note here is that by default Spring doesn't autowire and you have to provide explicit wiring using ref attribute for the properties or for constructor-args which are to be dependency injected.

Let's see examples of autowiring using XML configuration in Spring with all the autowiring modes as stated above.

Autowiring in Spring using byName

When you are autowiring by name the auto wired bean will look for the bean with the same name/id in the configuration file.

Let's see it with an example-

Here we have a class PayServiceImpl which has a field payment of type IPayment which we have to autowire.

interface IPayService

public interface IPayService {
 void performPayment();
}

PayServiceImpl class

public class PayServiceImpl implements IPayService {
  private IPayment payment;
  private int amount;

  public void performPayment() {
    // calling payment class executePayment method
    payment.executePayment(amount);
  }

  public IPayment getPayment() {
    return payment;
  }


  public void setPayment(IPayment payment) {
    this.payment = payment;
  }

  public int getAmount() {
    return amount;
  }

  public void setAmount(int amount) {
    this.amount = amount;
  }
}

interface IPayment

public interface IPayment {
 void executePayment(int amount);
}

CashPayment class

public class CashPayment implements IPayment{
 public void executePayment(int amount) {
  System.out.println("Perform Cash Payment for amount ... " + amount); 
 }
}

Configuration file

<?xml version="1.0" encoding="UTF-8"?>
<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-4.0.xsd">
 
 <!-- defining CashPayment bean -->
 <bean id="payment" class="org.netjs.springexp.prog.CashPayment" />
 
 <!-- Defining PayServiceImpl bean and injecting payment bean -->
 <bean id="payServiceBean" class="org.netjs.springexp.prog.PayServiceImpl" autowire="byName">
     <property name="amount" value="20" />
  </bean>
</beans>

Here notice that for the bean PayServiceImpl autowire=byName is used. In that case Spring will see that PayServiceImpl has one property named as payment so it will look for the bean with same name/id in the config file. Since there is a bean with id as payment so that bean will be injected.

You can run it using the following program-

public class App {
  public static void main(String[] args) {
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext
      ("appcontext.xml");
    IPayService bean = (IPayService) context.getBean("payServiceBean");
    bean.performPayment();
    context.close();
  }
}

Output

Perform Cash Payment for amount ... 20

Autowiring in Spring using byType

When you are autowring by type the property's type in auto wired bean will be used for searching the bean with the compatible type in the configuration file.

You can use the same example as above only change will be in the configuration file to change the autowire=byType.

<bean id="payServiceBean" class="org.netjs.springexp.prog.PayServiceImpl" autowire="byType">
     <property name="amount" value="20" />
</bean>

In the config file there is a bean of type Payment which matches the type of the payment field in the PayServiceImpl class. Thus autowiring by type will work.

Limitation with autowire="byType"

There is one problem with using autowiring as byType. What if there are more than one bean in the configuration file whose type is compatible with the autowired property. In that case Spring won't be able to decide which bean to use, it will throw an exception instead. To see an example of this problem you need to create one more class which implements IPayment interface. Let's say with CashPayment there is also an option for CreditPayment.

CreditPayment class

public class CreditPayment implements IPayment {
 public void executePayment(int amount) {
  System.out.println("Perform Credit Payment for amount ... " + amount);
 }
}

In the config file also the definition is added.

<!-- defining CreditPayment bean -->
<bean id="creditPayment" class="org.netjs.springexp.prog.CreditPayment" />

Now there are two beans of type IPayment in the config file. In that case if we run the program Spring won't be able to decide which one to inject either CashPayment or CreditPayment so it will throw UnsatisfiedDependencyException instead.

Output

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 
'payServiceBean' defined in class path resource [appcontext.xml]: Unsatisfied dependency expressed 
through bean property 'payment': : No qualifying bean of type [org.netjs.springexp.prog.IPayment] is defined: 
expected single matching bean but found 2: payment,creditPayment; nested exception is 
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 
[org.netjs.springexp.prog.IPayment] is defined: expected single matching bean but found 2: payment,creditPayment
 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireByType
 (AbstractAutowireCapableBeanFactory.java:1307)

Solving UnsatisfiedDependencyException with Spring autowiring

To overcome this problem there are two options-

  • primary candidate- Identify a primary candidate for auto wiring bean and set that as primary="true"
    <bean id="payment" class="org.netjs.springexp.prog.CashPayment" primary="true"/>
    
  • Exclude a bean from autowiring- You can exclude a bean from being autowired. For that set the autowire-candidate attribute of <bean> tag to false.
    <bean id="creditPayment" class="org.netjs.springexp.prog.CreditPayment" autowire-candidate="false" />
    

Autowiring in Spring by constructor

Autowiring by constructor is same like byType in this case type of the constructor argument in the auto wired bean is used to search the bean with the same type.

If you change the PayServiceImpl class to have a constructor which has a IPayment type as a parameter.

public class PayServiceImpl implements IPayService {
 private IPayment payment;
 private int amount;
 
 // Constructor
 PayServiceImpl(IPayment payment){
   this.payment = payment;
 }
  
 public void performPayment() {
  // calling payment class executePayment method
  payment.executePayment(amount);
 }

 public int getAmount() {
  return amount;
 }

 public void setAmount(int amount) {
  this.amount = amount;
 }
}

And change the configuration file as-

<bean id="payServiceBean" class="org.netjs.springexp.prog.PayServiceImpl" autowire="constructor">
     <property name="amount" value="20" />
</bean>

default-autowire attribute

If you are using the same autowire attribute with most of the bean in your config file, you can define that autowire attribute as default for all the beans with in the config file. That can be done by adding a default-autowire attribute to the root </beans> element.

<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-4.0.xsd" default-autowire="byType">

Here default auto wiring is set to byType which means all the beans in this config file will use auto wiring as byType by default. Note that by default default-autowire is set to none.

You can still set autowire attribute for individual beans which will override the default-autowire attribute.

That's all for this topic Autowiring in Spring Using XML Configuration. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Spring Tutorial Page


Related Topics

  1. Autowiring in Spring Using @Autowired and @Inject Annotations
  2. Spring Component Scan to Automatically Discover Beans
  3. Spring Java Configuration Example Using @Configuration
  4. @Conditional Annotation in Spring
  5. Circular Dependency in Spring Framework

You may also like-

  1. Injecting Inner Bean in Spring
  2. Data Access in Spring Framework
  3. Creating a Maven project in Eclipse
  4. static Keyword in Java With Examples
  5. Difference between ArrayList and LinkedList in Java
  6. LinkedHashSet in Java With Examples
  7. Lambda Expression Examples in Java
  8. Compress And Decompress File Using GZIP Format in Java

Monday, January 8, 2024

Benefits, Disadvantages And Limitations of Autowiring in Spring

Though autowiring in Spring makes life easy by wiring the dependencies automatically thus requiring less code to write but at the same time there are few limitations and disadvantages of autowiring in Spring too and that is the topic of this post.

Benefits of autowiring

  1. Using autowiring means you don't need to explicitly wire the bean properties, Spring will do it automatically. So autowiring requires less configuration code.
  2. Provides several modes for autowiring like byName, byType, constructor. So you have the flexibility to choose how you want to autowire the dependencies.

Disadvantages of autowiring in Spring

  1. Explicit wiring has an advantage that you can explicitly wire the bean you want but Autowiring is not that exact. For example, if you are using constructor autowiring and there is not exactly one bean of the constructor argument type in the container then Spring won't be able to determine which of those beans has to be wired. In case of ambiguity Spring autowiring won't try to guess instead it throws an exception.
  2. Wiring information may not be available to tools that may generate documentation from a Spring container.
  3. Within the container there may be multiple bean definitions matching the type specified by the setter method or constructor argument to be autowired. Within the container there may be multiple bean definitions matching the type specified by the setter method or constructor argument to be autowired. In that case Spring won't be able to decide which bean to use for autowiring. If no unique bean definition is available, an exception is thrown.

Limitations of autowiring

  1. Explicit dependencies in property and constructor-arg settings always override autowiring.
  2. You cannot autowire so-called simple properties such as primitives, Strings, and Classes (and arrays of such simple properties). This limitation in autowiring is by-design.

Reference- https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html

That's all for this topic Benefits, Disadvantages And Limitations of Autowiring in Spring. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Spring Tutorial Page


Related Topics

  1. Autowiring in Spring Using XML Configuration
  2. Spring Component Scan to Automatically Discover Beans
  3. Excluding Bean From Autowiring in Spring
  4. @Resource Annotation in Spring Autowiring
  5. How to Inject Null And Empty String Values in Spring

You may also like-

  1. Bean Definition Inheritance in Spring
  2. Spring JdbcTemplate Select Query Example
  3. BeanFactoryAware Interface in Spring Framework
  4. How to Create Password Protected Zip File in Java
  5. static Block in Java
  6. Transient Keyword in Java With Examples
  7. Volatile Keyword in Java With Examples
  8. Difference Between CountDownLatch And CyclicBarrier in Java

Friday, January 6, 2023

Excluding Bean From Autowiring in Spring

You can exclude a bean from autowiring in Spring framework per-bean basis. If you are using Spring XML configuration then you can exclude a bean from autowiring by setting the autowire-candidate attribute of the <bean/> element to false. That way container makes that specific bean definition unavailable to the autowiring infrastructure.

Excluding bean using autowire-candidate example

Here we have a class PayServiceImpl which has a field payment of type IPayment which we have to autowire. Also there are two classes CashPayment and CardPayment which implements IPayment interface.

IpayService interface

public interface IPayService{
 void performPayment();
}

PayServiceImpl class

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

public class PayServiceImpl implements IPayService{
 @Autowired
 private IPayment payment;
 
 public void setPayment(IPayment payment) {
  this.payment = payment;
 }

 public void performPayment() {
  System.out.println("performPayment Method called");
  payment.executePayment();
 }
}

Here note the @Autowired annotation on payment field.

Interface Ipayment

public interface IPayment{
 void executePayment();
}

CashPayment class

public class CashPayment implements IPayment{
 
 public void executePayment() {
  System.out.println("Perform Cash Payment "); 
 }
}

CardPayment class

public class CardPayment implements IPayment{
 public void executePayment() {
  System.out.println("Perform Card Payment "); 
 }
}

XML Configuration

<?xml version="1.0" encoding="UTF-8"?>
<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-4.0.xsd
  http://www.springframework.org/schema/context
  http://www.springframework.org/schema/context/spring-context.xsd">
  
  <context:annotation-config/>
   
  <bean id="cash" class="org.netjs.exp.Spring_Example.CashPayment" />
  <bean id="card" class="org.netjs.exp.Spring_Example.CardPayment" />
 
  <bean id="payServiceBean" class="org.netjs.exp.Spring_Example.PayServiceImpl">
  </bean>
</beans>

Here we have defined two beans of type Ipayment, CashPayment and CardPayment. This will result in BeanCreationException as container won’t be able to decide which on of the two inject in PayServiceImpl class.

You can check that by running the code using the following Java class.

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

public class App {
  public static void main( String[] args ){
    AbstractApplicationContext context = new ClassPathXmlApplicationContext
       ("appcontext.xml");

    IPayService payBean = (IPayService)context.getBean("payServiceBean");
    payBean.performPayment();
    context.registerShutdownHook();
  } 
}

Output

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'payServiceBean': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.netjs.exp.Spring_Example.IPayment org.netjs.exp.Spring_Example.PayServiceImpl.payment; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [org.netjs.exp.Spring_Example.IPayment] is defined: expected single matching bean but found 2: cash,card

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [org.netjs.exp.Spring_Example.IPayment] is defined: expected single matching bean but found 2: cash,card

If you set autowire-candidate attribute as false for one of the bean then the problem will be resolved.

<bean id="cash" class="org.netjs.exp.Spring_Example.CashPayment" autowire-candidate="false" />

With this change if you run the code, card bean will be injected.

Output

performPayment Method called
Perform Card Payment 

Resolving conflict with annotations

If you want to use annotations to resolve conflict in this type of situation when you have more than one bean defined of the same type. Then you have two options.

  1. @Qualifier annotation.
  2. @Inject and @Named annotation

Using @Qualifier annotation example

In the example used above where you have two beans CardPayment and CashPayment of the same type, in order to avoid ambiguity you can use @Qualifier annotation to qualify the bean.

Suppose you want to inject cashPaymentBean then you can qualify it by passing bean name with the qualifier annotation in the PayServiceImpl class.

PayServiceImpl.java

public class PayServiceImpl implements IPayService{
 @Autowired
 @Qualifier("cash")
 private IPayment payment;
 
 public void setPayment(IPayment payment) {
  this.payment = payment;
 }

 public void performPayment() {
  System.out.println("performPayment Method called");
  payment.executePayment();
 }
}

Now even if you don’t set autowire-candidate as false for any of the bean that’s ok as @Qualifier annotation will resolve the conflict.

<bean id="cash" class="org.netjs.exp.Spring_Example.CashPayment" />
<bean id="card" class="org.netjs.exp.Spring_Example.CardPayment" />

Using @Inject and @Named annotations

If you want to make sure that CashPayment bean is the one which is injected then using @Inject and @Named annotations the PayServiceImpl class will look like-

import javax.inject.Inject;
import javax.inject.Named;

public class PayServiceImpl implements IPayService{
 @Inject
 @Named("cash")
 private IPayment payment;
 
 public void setPayment(IPayment payment) {
  this.payment = payment;
 }


 public void performPayment() {
  System.out.println("performPayment Method called");
  payment.executePayment();
 }
}

Note that you will need to import javax.inject jar in order to use these annotations. In Maven you can do it by adding the following dependency.

<dependency>
  <groupId>javax.inject</groupId>
  <artifactId>javax.inject</artifactId>
  <version>1</version>
</dependency>

That's all for this topic Excluding Bean From Autowiring in Spring. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Spring Tutorial Page


Related Topics

  1. Autowiring in Spring Using XML Configuration
  2. Autowiring in Spring Using @Autowired and @Inject Annotations
  3. Benefits, Disadvantages And Limitations of Autowiring in Spring
  4. Spring MessageSource Internationalization (i18n) Support
  5. Spring Object XML Mapping (OXM) JAXB Example

You may also like-

  1. Spring depends-on Attribute and @DependsOn With Examples
  2. Bean Definition Inheritance in Spring
  3. Spring Batch Processing Using JDBCTemplate batchUpdate() Method
  4. Spring MVC @PathVariable Example - Creating Dynamic URL
  5. Java String substring() Method - Getting Substring
  6. PermGen Space Removal in Java 8
  7. Java Nested Class And Inner Class
  8. Java Multithreading Interview Questions And Answers

Monday, January 2, 2023

@Resource Annotation in Spring Autowiring

Apart from supporting JSR-330 annotations like @Inject and @Named for autowiring, Spring also supports injection using the JSR-250 @Resource annotation on fields or bean property setter methods.

Spring @Resource annotation

@Resource annotation in Spring takes a name attribute, and by default Spring interprets that value as the bean name to be injected. In other words, it follows by-name semantics. That's where it differs from other annotations for autowiring like @Autowired and @Inject which are equivalent to autowiring="byType" in autowiring using XML configuration file.

In case no name is provided with @Resource annotation explicitly, the default name is derived from the field name or setter method.

  • In case of a field, it takes the field name;
  • In case of a setter method, it takes the bean property name.

For example, if we take the following class then bean with name "payment" will be injected into its setter method

public class PayServiceImpl {

 private IPayCash payment;

 @Resource
 public void setPayment(IPayCash payment) {
  this.payment = payment;
 }
}

But there is also default switching with @Resource annotation, if it doesn't find the bean with the same name it will try to match using type. So if you see how it compares with the other two annotations @Autowired and @Inject in terms of ordering followed for autowiring-

@Autowired and @Inject annotations

  1. Matches by Type
  2. Restricts by Qualifiers
  3. Matches by Name

@Resource annotation in Spring

  1. Matches by Name
  2. Matches by Type
  3. Restricts by Qualifiers (ignored if match is found by name)

So you can see in case of @Autowired and @Inject switch to "byType" happens only after restricting by Qualifier. Whereas with @Resource it switches to byType if it doesn't find the bean by name.

Another difference between these two types of annotation is that @Autowired and @Inject annotations use the 'AutowiredAnnotationBeanPostProcessor' to inject dependencies. Whereas '@Resource' annotation uses the 'CommonAnnotationBeanPostProcessor' to inject dependencies.

Source : http://stackoverflow.com/questions/4093504/resource-vs-autowired

Spring @Resource annotation example

Here we have a class PayServiceImpl which has a field payment of type IPayment which we have to autowire. Also class CashPayment which implements IPayment interface.

PayServiceImpl class

import javax.annotation.Resource;

public class PayServiceImpl {
 
 @Resource(name="cashPaymentBean")
 private IPayment payment;
 
 public void performPayment() {
  payment.executePayment();
 }
 
 public IPayment getPayment() {
  return payment;
 }
 public void setPayment(IPayment payment) {
  this.payment = payment;
 }
}

Here note the @Resource annotation with name attribute on the field payment.

Interface IPayment

public interface IPayment {
 void executePayment();
}

CashPayment class

public class CashPayment implements IPayment{
 public void executePayment() {
  System.out.println("Perform Cash Payment "); 
 }
}

XML configuration file

<?xml version="1.0" encoding="UTF-8"?>
<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-4.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">
  
  <context:annotation-config />    
 
 <!-- defining CashPayment bean -->
  <bean id="cashPaymentBean" class="org.netjs.exp.Spring_Example.CashPayment" />
 
  <!-- Defining PayServiceImpl bean and injecting payment bean -->
  <bean id="payServiceBean" class="org.netjs.exp.Spring_Example.PayServiceImpl" >
  <!--     <property name="payment" ref="cashPaymentBean" /> -->
  </bean>
</beans>

Here note that the CashPayment class bean is defined with the same name "cashPaymentBean" as used in the @Resource annotation. <context:annotation-config /> tag is added which is required for autowired annotation. Also note that ref for cashPaymentBean is no longer required as a property in paymentBean (it is commented in the config).

You can use the following code to run this program -

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App 
{
    public static void main( String[] args ){
         ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext
          ("appcontext.xml");
         PayServiceImpl bean = (PayServiceImpl) context.getBean("payServiceBean");
         bean.performPayment();
         context.close();
    }
}

Switching to byType using @Resource annotation

As already mentioned @Resource annotation will switch to "byType" if it is not able to match the bean by name. You can test it by removing the "name" attribute from @Resource annotation.

@Resource
private IPayment payment;

In this case autowiring will be tried by looking for the bean named "payment". Since it is not there so it will match by type and the program will still run.

BeanNotOfRequiredTypeException when using @Resource annotation

Since @Resource annotation tries to match by Name and then by type that may result in exception in some scenarios. Let's see an example. Here we have one more interface IPayCash and field payment in class PayServiceImpl is of type IPayCash.

IPayCash interface

public interface IPayCash {
 void executePayment();
}

PayServiceImpl class

import javax.annotation.Resource;

public class PayServiceImpl {
 
 @Resource(name="cashPaymentBean")
 private IPayCash payment;
 
 
 public void performPayment() {
  payment.executePayment();
 }
 
 public IPayCash getPayment() {
  return payment;
 }
 public void setPayment(IPayCash payment) {
  this.payment = payment;
 }
}

XML configuration

<?xml version="1.0" encoding="UTF-8"?>
<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-4.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">
  
  <context:annotation-config />    
 
 <!-- defining CashPayment bean -->
  <bean id="cashPaymentBean" class="org.netjs.exp.Spring_Example.CashPayment" />
 
  <!-- Defining PayServiceImpl bean and injecting payment bean -->
  <bean id="payServiceBean" class="org.netjs.exp.Spring_Example.PayServiceImpl" >
  <!--     <property name="payment" ref="cashPaymentBean" /> -->
  </bean>
</beans>

If you see here in XML configuration CashPayment bean is defined with id "cashPaymentBean" and in Class PayServiceImpl @Resource annotation also has the same name attribute @Resource(name="cashPaymentBean") so name matching will happen without any problem.

If you have noticed types are different, in XML configuration cashPaymentBean is defined as an instance of CashPayment class which is of type IPayment, whereas in PayServiceImpl payment field is of type IPayCash. Thus at run time, because of type mismatch, "BeanNotOfRequiredTypeException" is thrown.

Output

WARNING: Exception encountered during context initialization - cancelling refresh attempt
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'payServiceBean': 
Injection of resource dependencies failed; nested exception is 
org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'cashPaymentBean' 
must be of type [org.netjs.exp.Spring_Example.IPayCash], but was actually of type 
[org.netjs.exp.Spring_Example.CashPayment]
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:311)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:305)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:301)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:834)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:537)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
    at org.netjs.exp.Spring_Example.App.main(App.java:10)

That's all for this topic @Resource Annotation in Spring Autowiring. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Spring Tutorial Page


Related Topics

  1. Autowiring in Spring Using @Autowired and @Inject Annotations
  2. Spring Component Scan to Automatically Discover Beans
  3. Spring Component Scan Example
  4. Using Conditional Annotation in Spring Framework
  5. BeanPostProcessor in Spring Framework

You may also like-

  1. Bean Definition Inheritance in Spring
  2. Constructor-Based Dependency Injection in Spring
  3. Spring JdbcTemplate Select Query Example
  4. Lazy Initialization in Spring Using lazy-init And @Lazy Annotation
  5. Lambda Expression Examples in Java
  6. How to Find Last Modified Date of a File in Java
  7. Interface Default Methods in Java
  8. Java BlockingQueue With Examples

Sunday, January 3, 2021

Spring Component Scan to Automatically Discover Beans

In the post how to autowire using XML config and how to autowire using annotation you have already seen how Spring can automate the injection of dependencies. That helps in cutting down the configuration you have to do by eliminating the use of <property> and <constructor-arg> tags for wiring the bean references. But Spring can even automatically discover beans using <context:component-scan> element. In this post we'll see how to configure and use component scanning in Spring.


Automatic discovery of beans in Spring

Spring goes even further than autowiring and it can automatically discover beans for you. That can be done using <context:component-scan> element or @ComponentScan annotation, it configures Spring to automatically discover beans and declare them for you. This removes the need to use XML to perform bean registration and for most of the classes you don’t need <bean> element to declare and wire beans.

Note here that - The use of <context:component-scan> implicitly enables the functionality of <context:annotation-config>. There is usually no need to include the <context:annotation-config> element when using <context:component-scan>. So <context:component-scan> will do everything which <context:annotation-config> does and it provides the added functionality of auto-discovery of beans. In fact difference between <context:annotation-config> and <context:component-scan> is one of the frequently asked interview question.

Spring component scan configuration requirement

If you are using XML configuration then you need to use context:component-scan with base-package. The base-package attribute tells <context:component-scan> from which package it needs to start its component scan.

<?xml version="1.0" encoding="UTF-8"?>
<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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
    <context:component-scan base-package="org.example"/>
</beans>

If you are using Spring Java configuration then you need to add @ComponentScan annotation along with @Configuration annotation-

@Configuration
@ComponentScan(basePackages="org.example")
public class AppConfig {
    
}

You can annotate a Java class with @ComponentScan and provide the package which is to be scanned with basePackage attribute. You don't need to provide any code with in the class.

Annotations used in Spring for auto-discovery

Using componentscan element is half of the picture, you need to annotate your classes which needs to be auto-discovered with one of these annotations @Component, @Service, @Controller, @Repository

  • @Component- It is a generic stereotype for any Spring-managed component.
  • @Service- More suitable for a class used as a service.
  • @Repository- This annotation is a marker for any class that fulfills the role or stereotype of a repository (also known as Data Access Object or DAO).
  • @Controller- More suitable for a class used in presentation layer as a controller.
  • Any custom annotation that is itself annotated with @Component.

According to the Spring reference doc-

"you can annotate your component classes with @Component, but by annotating them with @Repository, @Service, or @Controller instead, your classes are more properly suited for processing by tools or associating with aspects. For example, these stereotype annotations make ideal targets for pointcuts. It is also possible that @Repository, @Service, and @Controller may carry additional semantics in future releases of the Spring Framework."

Spring component scanning example

Here we have a class PayServiceImpl which has a field payment of type IPayment which we have to autowire. Also PayServiceImpl and CashPayment (implementing class of interface IPayment) should be auto discovered. Since Spring promotes loose coupling so it is always recommended to code to interfaces. So we'll also create interfaces for the classes.

IPayService Interface

public interface IPayService {
 void performPayment();
}

PayServiceImpl class

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

@Service
public class PayServiceImpl implements IPayService {
 @Autowired
 private IPayment payment;

 public void performPayment() {
  // calling method on Ipayment implementing class
  payment.executePayment();
 }
 
 public IPayment getPayment() {
  return payment;
 }
 
 public void setPayment(IPayment payment) {
  this.payment = payment;
 }
}

Here note that the class is annotated with @Service annotation, that's how it is made sure that this class is discovered while a component scan is done. Also note that the dependency to the payment is annotated with the annotation @Autowired. That's how Spring will automatically detect this dependency and inject it.

Interface IPayment

public interface IPayment {
 void executePayment();
}

Class CashPayment

import org.springframework.stereotype.Component;

@Component
public class CashPayment implements IPayment{
 public void executePayment() {
  System.out.println("Perform Cash Payment - "); 
 }
}

Spring component scan XML Configuration

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">
 
   <context:component-scan base-package="org.netjs.prog" />  
 
</beans>

If you are using XML configuration then you need to use context:component-scan with base-package. I have created Java classes in the package org.netjs.prog so that's what I'll give as the base package. Please change accordingly.

You can run it using the following program-

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
  public static void main( String[] args ){  
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext
     ("appcontext.xml");
    IPayService bean = (IPayService) context.getBean("payServiceImpl");
    bean.performPayment();
    context.close();
  }
}

Here note that by default Spring will use the class name as the bean id (camel cased) while registering it in Spring. That's why you can find the bean using this- context.getBean("payServiceImpl");

If you want to give your own name let's say payService then it can be done like this-

@Service("payService")
public class PayServiceImpl implements IPayService

Then in order to get the bean you have to use this name -

IPayService bean = (IPayService) context.getBean("payService");

Spring component scan example with Java config

If you are using Java class then you just need this

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan(basePackages="org.netjs.prog")
public class AppConfig {
 
}

In that case you can run it using the following program-

import org.netjs.config.AppConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;

public class App {
  public static void main( String[] args ){
    AbstractApplicationContext context = new AnnotationConfigApplicationContext
     (AppConfig.class);
    IPayService bean = (IPayService) context.getBean("payServiceImpl");
    bean.performPayment();
    context.close();
  }
}

Here note that AnnotationConfigApplicationContext is used to create the Spring application context which takes the JavaConfig class as input.

That's all for this topic Spring Component Scan to Automatically Discover Beans. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Spring Tutorial Page


Related Topics

  1. Spring Constructor Based Dependency Injection
  2. Spring Java Configuration Example Using @Configuration
  3. Autowiring in Spring Using @Autowired and @Inject Annotations
  4. Autowiring in Spring Using XML Configuration
  5. @Conditional Annotation in Spring

You may also like-

  1. How to Read Properties File in Spring Framework
  2. @Resource Annotation in Spring Autowiring
  3. Circular Dependency in Spring Framework
  4. Java LinkedBlockingQueue With Examples
  5. Java ThreadLocal Class With Examples
  6. Abstraction in Java
  7. How HashMap Works Internally in Java
  8. Print Odd-Even Numbers Using Threads And wait-notify Java Program

Saturday, January 2, 2021

Autowiring in Spring Using @Autowired and @Inject Annotations

Though autowiring of the beans can be done using XML configuration for autowiring but Spring goes one step further and provides autowiring using annotations which leads to shorter and more concise configuration.

Broadly Spring provides two ways to annotate beans for autowiring-

  • Using @Autowired annotation- It is a spring specific annotation.
  • Using @Inject annotation- It is provided by JSR-330 (Dependency Injection for Java) annotations contained in the javax.inject package. Spring supports this annotation.

In this post we'll see Spring autowiring examples using both @Autowired and @Inject annotations.


Configuration required for autowiring using annotation

To enable autowiring using annotation in Spring, you have to register 'AutowiredAnnotationBeanPostProcessor' class.

  • You can directly provide this class in xml config-
    <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
    
  • You can include the <context:annotation-config/> tag in an XML-based Spring configuration (notice the inclusion of the context namespace in XML). This is the preferred way.
    <?xml version="1.0" encoding="UTF-8"?>
    <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.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">
      <context:annotation-config/>
    </beans>
    

    By using <context:annotation-config/> tag following post-processors are implicitly registered AutowiredAnnotationBeanPostProcessor, CommonAnnotationBeanPostProcessor, PersistenceAnnotationBeanPostProcessor and RequiredAnnotationBeanPostProcessor.

  • You can include the <context:component-scan/> tag.

Refer Using component-scan in Spring to Automatically Discover Bean to see why <context:component-scan/> should be used instead of <context:annotation-config/>

Autowiring in Spring using @Autowired annotation

Note that @Autowired annotation can be applied on-

  • setter method
  • constructor
  • field
Here we'll see example for all of these options.

Spring @Autowired annotation on setter

When @Autowired annotation is used on a setter, it is equivalent to autowiring="byType" in autowiring using configuration file.

Here we have a class PayServiceImpl which has a field payment of type IPayment which we have to autowire. Also class CashPayment which implements IPayment interface.

interface IPayService

public interface IPayService {
 void performPayment();
}

PayServiceImpl class

import org.springframework.beans.factory.annotation.Autowired;
public class PayServiceImpl implements IPayService {
  private IPayment payment;

  public void performPayment() {
    // calling method on Ipayment implementing class
    payment.executePayment();
  }

  public IPayment getPayment() {
    return payment;
  }

  @Autowired
  public void setPayment(IPayment payment) {
    this.payment = payment;
  }
}

Here note the @Autowired annotation on setPayment() method.

Interface IPayment

public interface IPayment {
 void executePayment();
}

CashPayment class

public class CashPayment implements IPayment{
 public void executePayment() {
  System.out.println("Perform Cash Payment - "); 
 }
}

XML configuration file

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

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">
 
 <context:annotation-config/>  
 
 <bean id="cashPaymentBean" class="org.netjs.prog.CashPayment" />
 
  <!-- Defining PayServiceImpl bean and injecting payment bean -->
  <bean id="paymentBean" class="org.netjs.prog.PayServiceImpl">
      <!-- <property name="payment" ref="cashPaymentBean" /> -->
  </bean> 
</beans>

Here note the inclusion of <context:annotation-config/> tag which is required for autowired annotation. Also note that ref for cashPaymentBean is no longer required as a property in paymentBean (it is commented in the config). It will be injected automatically now because of the @Autowired annotation.

You can use the following code to run this program -

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
  public static void main( String[] args ){  
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext
       ("appcontext.xml");
    // Getting PayServiceImpl 
    IPayService bean = (IPayService) context.getBean("paymentBean");
    bean.performPayment();
    context.close();
  }
}

Output

Perform Cash Payment-

@Autowired annotation on field

When @Autowired annotation is used on a property, it is equivalent to autowiring="byType" when autowiring is done using configuration file.

In this case PayServiceImpl will change to have @Autowired annotation on the field. When using @Autowired with field you don't even need the setter method for that field.

PayServiceImpl class

public class PayServiceImpl implements IPayService {
 @Autowired
 private IPayment payment;

 public void performPayment() {
  // calling method on Ipayment implementing class
  payment.executePayment();
 }
 
 public IPayment getPayment() {
  return payment;
 }
 
 /*public void setPayment(IPayment payment) {
  this.payment = payment;
 }*/
}

Rest of the things remain the same as used in the example for @Autowired on setter.

@Autowired annotation on constructor

When @Autowired annotation is used on a bean's constructor, it is equivalent to autowiring="constructor" when autowiring is done using configuration file.

In this case PayServiceImpl will change to have @Autowired annotation on the constructor of the class. When using @Autowired on constructor you don't even need the setter method for that field.

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

public class PayServiceImpl implements IPayService {
 
 private IPayment payment;
 // Constructor 
 @Autowired
 PayServiceImpl(IPayment payment){
  this.payment = payment;
 }

 public void performPayment() {
  // calling method on Ipayment implementing class
  payment.executePayment();
 }
 
 public IPayment getPayment() {
  return payment;
 }
 
 /*public void setPayment(IPayment payment) {
  this.payment = payment;
 }*/
}

Rest of the things remain the same as used in the example for @Autowired on setter.

@Autowired annotation on arbitrary methods

You can also apply the annotation to methods with arbitrary names and/or multiple arguments, Example as taken from Spring reference doc

public class MovieRecommender {
  private MovieCatalog movieCatalog;
  private CustomerPreferenceDao customerPreferenceDao;
  @Autowired
 public void prepare(MovieCatalog movieCatalog, CustomerPreferenceDao customerPreferenceDao) {
   this.movieCatalog = movieCatalog;
   this.customerPreferenceDao = customerPreferenceDao;
 }
 // ...
}

@Autowired annotation with required=false

The default behavior for the annotation is to treat annotated methods, constructors, and fields as indicating required dependencies. Thus the autowiring fails whenever zero candidate beans are available. You can make the autowiring optional to avoid such errors, this can be done by using required="false" with the @Autowired annotation.

@Autowired(required=false)
private IPayment payment;

Conflict resolution using Spring @Qualifier annotation

What if there are more than one bean in the configuration file whose type is compatible with the autowired property. In that case Spring won't be able to decide which bean to use, it will throw an exception instead.

In the above application we had used only one implementation of IPayment, CashPayment so there was no problem in automatically wiring it. Now suppose we have one more implementation of the IPayment interface, Credit Payment. In that case with the current setup you'll get NoUniqueBeanDefinitionException because Spring won't know which Payment class to wire.

CreditPayment class

public class CreditPayment implements IPayment {
 public void executePayment() {
  System.out.println("Performing credit payment ");
 }
}

Adding CreditPayment definition in config

<bean id="creditPaymentBean" class="org.netjs.prog.CreditPayment" />

Now if you run the code you will get NoUniqueBeanDefinitionException-

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'paymentBean': 
Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: 
Could not autowire field: private org.netjs.prog.IPayment org.netjs.prog.PayServiceImpl.payment; 
nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: 
No qualifying bean of type [org.netjs.prog.IPayment] is defined: expected single matching bean but found 2: 
cashPaymentBean,creditPaymentBean
 at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)
 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214)

In this kind of scenario, to avoid ambiguity you can use @Qualifier annotation to qualify the bean. Suppose you want to inject cashPaymentBean then you can qualify it by passing bean name with the qualifier annotation.

@Qualifier example to avoid NoUniqueBeanDefinitionException error

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

public class PayServiceImpl implements IPayService {
 @Autowired
 @Qualifier("cashPaymentBean")
 private IPayment payment;

 public void performPayment() {
  // calling method on Ipayment implementing class
  payment.executePayment();
 }
 
 public IPayment getPayment() {
  return payment;
 }
 
 /*public void setPayment(IPayment payment) {
  this.payment = payment;
 }*/
}

Using JSR-330 @Inject annotation

Instead of @Autowired, @javax.inject.Inject annotation can be used for autowiring in Spring. @Inject annotation is part of the standard JSR-330: Dependency injection for Java. So, if you don't want Spring specific annotations and want to go with standard annotation then use @Inject.

As with @Autowired, it is possible to use @Inject at the class-level, field-level, method-level and constructor-argument level.

Note one thing though. @Inject has no 'required' attribute as provided with @Autowired, so @Inject annotated dependencies can't be optional, an exception will be thrown if they are not fulfilled.

@Named annotation

If you would like to use a qualified name for the dependency that should be injected, instead of @Qualifier you can use @Named annotation which is again part of the standard JSR-330: Dependency injection for Java.

Spring autowiring example with @Inject and @Named annotations

Let's take the same case where we have two payment classes CashPayment and CreditPayment. If you want to make sure that CashPayment bean is the one which is injected then using @Inject and @Named annotations the PayServiceImpl class will look like -

import javax.inject.Inject;
import javax.inject.Named;

public class PayServiceImpl implements IPayService {
 @Inject
 @Named("cashPaymentBean")
 private IPayment payment;

 public void performPayment() {
  // calling method on Ipayment implementing class
  payment.executePayment();
 }
 
 public IPayment getPayment() {
  return payment;
 }
 
 @Inject
 public void setPayment(@Named("cashPaymentBean")IPayment payment) {
  this.payment = payment;
 }
}

Note here that @Inject annotation is used with the setter.

Configuration file for the example

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">
 
 <context:annotation-config/>  
 
 <bean id="cashPaymentBean" class="org.netjs.prog.CashPayment" />
 
 <bean id="creditPaymentBean" class="org.netjs.prog.CreditPayment" />
 
  <!-- Defining PayServiceImpl bean and injecting payment bean -->
  <bean id="paymentBean" class="org.netjs.prog.PayServiceImpl">
  </bean>
</beans>

Are annotations better than XML for configuring Spring?

According to the Spring reference doc-

The introduction of annotation-based configurations raised the question of whether this approach is 'better' than XML. The short answer is it depends. The long answer is that each approach has its pros and cons, and usually it is up to the developer to decide which strategy suits them better. Due to the way they are defined, annotations provide a lot of context in their declaration, leading to shorter and more concise configuration. However, XML excels at wiring up components without touching their source code or recompiling them. Some developers prefer having the wiring close to the source while others argue that annotated classes are no longer POJOs and, furthermore, that the configuration becomes decentralized and harder to control.

That's all for this topic Autowiring in Spring Using @Autowired and @Inject Annotations. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Spring Tutorial Page


Related Topics

  1. Autowiring in Spring Using XML Configuration
  2. Dependency Injection in Spring Framework
  3. How to Read Properties File in Spring Framework
  4. Difference Between component-scan And annotation-config in Spring
  5. @Resource Annotation in Spring Autowiring

You may also like-

  1. Bean Definition Inheritance in Spring
  2. Spring p-namespace For Shorter XML Configuration
  3. Spring NamedParameterJdbcTemplate Insert, Update And Delete Example
  4. Difference Between throw And throws in Java
  5. How to Sort an ArrayList in Descending Order in Java
  6. LinkedHashMap in Java With Examples
  7. How to Create PDF From XML Using Apache FOP
  8. How to Find Last Modified Date of a File in Java

Difference Between component-scan And annotation-config in Spring

To understand the difference between <context:annotation-config/> element and <context:component-scan> element in Spring you have to know about two terms-

  • Autowiring of beans
  • Autodiscovery of beans

Autowiring of beans in Spring

When you use only XML configuration for registering your beans and defining dependencies then you need to configure everything manually in your XML.

As Example If you have 2 classes PayServiceImpl and CashPayment where PayServiceImpl uses object of CashPayment class then in your spring configuration you will have something like this -

<?xml version="1.0" encoding="UTF-8"?>
<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-4.0.xsd">
 
 <!-- defining CashPayment bean -->
  <bean id="cashPaymentBean" class="org.netjs.exp.Spring_Example.CashPayment" />
 
  <!-- Defining PayServiceImpl bean and injecting payment bean -->
  <bean id="payServiceBean" class="org.netjs.exp.Spring_Example.PayServiceImpl">
      <property name="payment" ref="cashPaymentBean" />
  </bean>
</beans>

If you use autowiring then also you have two options-

In case you use annotations, you need to activate annotations and you have to add <context:annotation-config /> in your XML file.

With that if we take the same example as above the configuration will be like this-

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

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">
 
   <context:annotation-config/>  
 
   <bean id="cashPaymentBean" class="org.netjs.prog.CashPayment" />
 
   <!-- Defining PayServiceImpl bean and injecting payment bean -->
   <bean id="paymentBean" class="org.netjs.prog.PayServiceImpl">
      <!-- <property name="payment" ref="cashPaymentBean" /> -->
   </bean> 
</beans>

Note the inclusion of <context:annotation-config /> and exclusion of <property name="payment" ref="cashPaymentBean" /> (it is commented).

You don't need property as the dependency will be injected automatically but you need one more change for that in your PayServiceImpl class. You need to use @Autowired annotation to autowire the payment property.

import org.springframework.beans.factory.annotation.Autowired;
public class PayServiceImpl implements IPayService {
  private IPayment payment;

  public void performPayment() {
    // calling method on Ipayment implementing class
    payment.executePayment();
  }

  public IPayment getPayment() {
    return payment;
  }

  @Autowired
  public void setPayment(IPayment payment) {
    this.payment = payment;
  }
}

Here points to note are-

  • You have to include <context:annotation-config /> in your XML for autowiring using annotation to work.
  • You don't need to manually write the dependencies with property or constructor-arg tag and ref attribute.
  • You still have to define all your beans because <context:annotation-config /> only works on beans registered within the application context. That's where enters the auto discovery of beans.

Autodiscovery of beans using Spring component scan

With autowiring you can simplify your XML configuration to the extent that you don't need to provide the dependencies. But auto-discovery goes one step further and eliminates the need to add the <bean> tag altogether in your xml.

That can be done using <context:component-scan> element and pointing the base package, it configures Spring to automatically discover beans and declare them for you.

This removes the need to use XML to perform bean registration and for most of the classes you don’t need <bean> element to declare and wire beans.

Annotations used for auto-discovery

Using componentscan element is half of the picture, you need to annotate your classes which needs to be auto-discovered with one of these annotations @Component, @Service, @Controller, @Repository

  • @Component- It is a generic stereotype for any Spring-managed component.
  • @Service- More suitable for a class used as a service.
  • @Repository- This annotation is a marker for any class that fulfills the role or stereotype of a repository (also known as Data Access Object or DAO).
  • @Controller- More suitable for a class used in presentation layer as a controller.
  • Any custom annotation that is itself annotated with @Component.

As example if you have 2 classes PayServiceImpl and CashPayment where PayServiceImpl uses object of CashPayment class then you configuration will look like this-

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">
 
    <context:component-scan base-package="org.netjs.prog" />  
 
</beans>

PayServiceImpl class

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

@Service
public class PayServiceImpl implements IPayService {
 @Autowired
 private IPayment payment;

 public void performPayment() {
  // calling method on Ipayment implementing class
  payment.executePayment();
 }
 
 public IPayment getPayment() {
  return payment;
 }
 
 public void setPayment(IPayment payment) {
  this.payment = payment;
 }
}

Here note that the class is annotated with @Service annotation, that's how it is made sure that this class is discovered while a component scan is done. Also note that the dependency to the payment is annotated with the annotation @Autowired. That's how Spring will detect and automatically do the dependency injection.

Class CashPayment

import org.springframework.stereotype.Component;

@Component
public class CashPayment implements IPayment{
 public void executePayment() {
  System.out.println("Perform Cash Payment - "); 
 }
}

<context:component-scan> Vs <context:annotation-config> in Spring

With the examples we have seen it's easy to list out the differences between <context:component-scan> and <context:annotation-config> in Spring framework.

  1. <context:annotation-config> tag scans and activates annotations for already registered beans in Spring's application context. Examples of the annotations this tag looks for are @Autowired, @Resource, @PostConstruct, @PreDestroy.
    <context:component-scan> tag can automatically detect the classes and register the corresponding beans in the Spring's application context along with scanning and activating for the annotations as done using <context:annotation-config>. For registring the beans the annotations this tag looks for are @Component, @Repository, @Service, @Controller
  2. The use of <context:component-scan> implicitly enables the functionality of <context:annotation-config>. There is usually no need to include the <context:annotation-config> element when using <context:component-scan>. So <context:component-scan> will do everything which <context:annotation-config> does and it provides the added functionality of auto-discovery of beans.

That's all for this topic Difference Between component-scan And annotation-config in Spring. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Spring Tutorial Page


Related Topics

  1. Spring Component Scan to Automatically Discover Beans
  2. Autowiring in Spring Using @Autowired and @Inject Annotations
  3. How to Inject Prototype Scoped Bean into a Singleton Bean in Spring
  4. Bean Scopes in Spring With Examples
  5. Spring Setter Based Dependency Injection

You may also like-

  1. Circular Dependency in Spring Framework
  2. BeanPostProcessor in Spring Framework
  3. Using Conditional Annotation in Spring Framework
  4. Creating a Maven project in Eclipse
  5. Lambda expressions in Java 8
  6. Check if Given String or Number is a Palindrome Java Program
  7. How to Read File From The Last Line in Java
  8. Difference Between ReentrantLock and Synchronized in Java