3

I know how to use Auto Components Scanning and Consctuctor Injection individually. http://www.mkyong.com/spring/spring-auto-scanning-components/ http://www.dzone.com/tutorials/java/spring/spring-bean-constructor-injection-1.html

Is it possible to use AutoComponent Scanning with Constructor Injection? While using Auto Component Scanning spring framework scans all classes pointed "base-package" and creates an instance of each by invoking each Constructor with no parameter. Lets say how to modify following class and related spring XML file.

package com.fb.common;
@Repository
public class Person {

    private String name;
    private int age;

    public Person(String name, int age){
        this.name=name;
        this.age=age;
    }

    public String toString(){
        return "Name: "+name+" Age:"+age;
    }

}

XML file

<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:component-scan base-package="com.fb.common" />

    <!--
    <bean id="person" class="com.fb.common.Person">
        <constructor-arg type="java.lang.String" value="DefaultName"/>
        <constructor-arg type="int" value="30"/>
    </bean>
    -->
</beans>
Community
  • 1
  • 1
Ahmet Karakaya
  • 9,899
  • 23
  • 86
  • 141

3 Answers3

3

You can do the following

@Inject // or @Autowired
public Person(@Value("DefaultName") String name, @Value("30") int age){
    this.name=name;
    this.age=age;
}

According to Bozho's answer here, spring frowns upon constructor injection. Maybe you shouldn't do this this way.

For the comment on your question, it should be in

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>${org.springframework-version}</version>
</dependency>

For @Inject, you'll need

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

but you can just use @Autowired provided by Spring.

Community
  • 1
  • 1
Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • I am not sure about the "spring frowns upon constructor injection" comment. From what I know spring encourages you to use whatever is appropriate for your java code. – gkamal May 22 '13 at 14:13
  • @gkamal Just putting it out there, also this article: http://steveschols.wordpress.com/2012/06/05/i-was-wrong-constructor-vs-setter-injection/. With the property placeholder you have in your question, it's a little better. – Sotirios Delimanolis May 22 '13 at 14:15
  • 1
    Possibly a bit late but... Historically, Spring favoured property injection, but moved away from that towards favouring constructor injection for 'required' dependencies a number of years ago now. – Gwyn Evans Mar 26 '14 at 22:54
3

You will need to add the @Value annotation to each of the constructor arguments

public Person(@Value("DefaultName")String name, @Value("30")int age){
    this.name=name;
    this.age=age;
}

Instead of hard coding the values you can use a property place holder to refer to properties defined in a property file.

public Person(@Value("${person.defaultName}")String name, @Value("${person.age}")int age){
    this.name=name;
    this.age=age;
}

Classes like Person (entities value objects) are not generally created as spring beans.

gkamal
  • 20,777
  • 4
  • 60
  • 57
2

If component scanning is enabled, spring will try to create a bean even though a bean of that class has already been defined in the spring config xml. However if the bean defined in the spring config file and the auto-discovered bean have the same name, spring will not to create a new bean while it does component scanning. If a bean does not have a no-args constructor, at-least one of the constructors must be auto-wired. If no constructor is auto-wired, spring will try to create an object using default no-args constructor. You can find more about this topic here

Fahim Farook
  • 1,482
  • 2
  • 14
  • 38