11

Well I've been watching some tutorials about Spring dependency injection as well as MVC, but I still seem to not understand how we can instantiate classes specifically?

I mean if for instance I have a variable

@Autowired
ClassA someObject;

How can I make spring create someObject as an Instance of ClassB which would extend ClassA? like someObject = new ClassB();

I don't really understand how it works in spring, does the ContextLoaderListener do it automatically or do we have to create some kind of configuration class where we specify exactly what spring should instantiate those classes to? (In this case I haven't seen that anywhere in the tutorials) If yes, then how do we specify and how does it look like? And how do we configure it to work in web.xml, etc?

Arturas M
  • 4,120
  • 18
  • 50
  • 80

4 Answers4

33

You can do it like this:

Interface:

package org.better.place

public interface SuperDuperInterface{
    public void saveWorld();
}

Implementation:

package org.better.place

import org.springframework.stereotype

@Component
public class SuperDuperClass implements SuperDuperInterface{
     public void saveWorld(){
          System.out.println("Done");
     }
}

Client:

package org.better.place

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

public class SuperDuperService{
       @Autowire
       private SuperDuperInterface superDuper;


       public void doIt(){
           superDuper.saveWorld();
       }

}

Now you have your interface defined, written an implementation and marked it as a component - docs here. Now only thing left is to tell spring where to find components so they can be used for autowiring.

<beans ...>

     <context:component-scan base-package="org.better.place"/>

</beans>
stites
  • 4,903
  • 5
  • 32
  • 43
Stefan
  • 990
  • 1
  • 6
  • 10
  • Thanks, sounds like a really awesome answer, I think I do get it now, I'll try it now. Another question, what if we would need to pass parameters to some constructor? How would it look like or what would we use? – Arturas M Dec 11 '12 at 07:24
  • You cannot use stereotype Annotations to mark constructor based beans. Either use a default constructor with autowired dependencies or resort to a Java / XML Bases configuration (remove the @Component annotation and the context:component-scan element). See this post here for details: http://www.javalobby.org/java/forums/t18396.html – Stefan Dec 11 '12 at 07:31
  • Is someone still reading this thread? My question is - how would you achieve the same without using @Autowired? – user1414745 May 15 '13 at 14:13
  • 8
    Cool, what if we have multiple implementations ? How would you autowire ? Because you are autowiring at service level right ? I tried to autowire the implementation directly and it fails. Can you explain. Thanks in advance ! – PavanSandeep Dec 19 '14 at 20:58
  • I have the same question as @PavanSandeep. Does anyone have an answer? – Triet Doan Feb 28 '18 at 16:15
  • @PavanSandeep if you have multiple implementations of an interface, you need to use the `@Qualifier` annotation (cf. https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-autowired-annotation-qualifiers): Given 2 implementations of an interface, each implementation gets a class level annotation with a unique qualifier, e. g. `@Qualifier("interfaceImpl1")` for the first implementation and `@Qualifier("interfaceImpl2")` for the second. A class that declares the interface as a dependency uses the `@Qualifier(...)` annotation to identify the implementation – JCvanDamme Jun 08 '21 at 20:47
  • I guess it would be fine to have multiple implementations, as long as only one of them is decorated with @Component? Like, in most cases, you would have your Mock Class, and Regular Class, and you would inject the mock class manually, so no need for decorator there, roght? – aurelia Jan 03 '22 at 16:05
1

You have to specify the type of the class that you want to create object of in your applicationContext.xml file or you can directly annotate that class with any of @Component , @Service or @Repository if you are using latest version of Spring. In web.xml, you have to specify path of xml files as a context-param to servlet, if you are using xml-based configuration.

Sumit Desai
  • 1,542
  • 9
  • 22
  • Alright, so i let's say I have to have only ClassB annotated with Component annotation and spring will automatically instantiate a new ClassB() object for me? if Both the ClassA and ClassB would be annotated with Component annotation what would spring then do? Do I understand this correctly? – Arturas M Dec 11 '12 at 07:08
  • 1
    If both are annotated with @Component, then while auto-wiring, you will have to use Qualifier annotation which instructs spring to inject that bean which is matching with name you provide with the qualifier. – Sumit Desai Dec 11 '12 at 07:10
  • 1
    Also consider using xml descriptors if this is a common case for you. – sorencito Dec 11 '12 at 07:24
0

Yes, you have to provide a context.xml file in which you specify the instances. Give it to the ApplicationContext and it will autowire all fields for you.

http://alvinalexander.com/blog/post/java/load-spring-application-context-file-java-swing-application

sorencito
  • 2,517
  • 20
  • 21
0

Best Practices

@RestController
@RequestMapping("/order")
public class OrderController {
    private final IOrderProducer _IOrderProducer;

    public OrderController(IOrderProducer iorderProducer) {
        this._IOrderProducer = iorderProducer;
    }

    @GetMapping("/OrderService")
    void get() {
        _IOrderProducer.CreateOrderProducer("This is a Producer");
    }
}

Interface

@Service
public interface IOrderProducer {
    void CreateOrderProducer(String message);
}

Implementation

public class OrderProducer implements  IOrderProducer{
    private KafkaTemplate<String, String> _template;

    public OrderProducer(KafkaTemplate<String, String> template) {
        this._template = template;
    }

    public void CreateOrderProducer(String message){
        this._template.send("Topic1", message);
    }
}

You need to include Project Lombok dependency in spring boot

Gradle implementation 'org.projectlombok:lombok'

San Jaisy
  • 15,327
  • 34
  • 171
  • 290