Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I use setter injection with java configuration in Spring?

I am trying to learn about setter injection in a SpringMVC web application, all of the examples I can find, show using xml. However, I was told that xml is deprecated and all new applications should be done with java configuration. Is this wrong, should I be using xml to configure my application?

Where should I be declaring the bean and how would I do it?

This is one of the examples I have seen, yet it is implemented with 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.xsd">

  <bean id="message"
      class="org.springbyexample.di.xml.SetterMessage">
    <property name="message" value="Spring is fun." />
  </bean>

</beans>
like image 756
Chris Avatar asked Mar 02 '17 16:03

Chris


People also ask

How does setter injection work in Spring?

Setter injection is a dependency injection in which the spring framework injects the dependency object using the setter method. The call first goes to no argument constructor and then to the setter method. It does not create any new bean instance.

Is it possible to inject a Spring bean via setter injection?

The injection in Spring is either done via setter, field or constructor injection. Classes which are managed by Spring DI must conform to the Java bean standard.

How do you inject a method in Spring?

13.3 How to use Method Injection We need to create an abstract method in Singleton class with return type as PrototypeBean . and Prototype bean class will declare one method which returns the current instance (this). Spring provides below tag that can be used for method injection.

Does Spring allow both constructor and setter injection?

The good thing about Spring is that it doesn't restrict you to use either Setter Injection or Constructor Injection and you are free to use both of them in one Spring configuration file.


2 Answers

I would recommend to look into plain Spring configuration first to get a feel of how fundamental things (like injection) work. If you manage to get a hang of it in Spring, the process will be very similar in Spring MVC/Spring Boot/etc. Personally, I find it very frustrating trying to juggle multiple concepts (view resolvers, different configuration files, views, repositories, multiple annotations, multiple ways of configuration, etc.) at once, so I tend to start from the simplest concepts and build my way up. Once you are comfortable with how injection works, you can easily apply this knowledge elsewhere.

As for java config and annotations, they do allow for much quicker and cleaner development. XML is quite verbose, hard to maintain and is very prone to errors, in part because IDEs are generally more helpful when working with java based configuration. Perhaps that is why you read that XML is being deprecated. I would recommend to go for java/auto configuration rather than XML one, unless you really need to (or are interested in it).

Now onto how to do it. A complete (but minimal) working Spring example:

/* Bean definition

@Component tells Spring that this is a bean. There are a few similar annotations.
It will be discovered during the component scan, as it has @Component annotation */

package main.java.org.example;
import org.springframework.stereotype.Component;

@Component 
public class Greeting {
    private String greeting = "Hello";

    public String getGreeting() {
        return this.greeting;
    }

    public void setGreeting(String greeting) {
        this.greeting = greeting;
    }
}


/* Another bean definition.
It has another bean as a dependency, which we inject with a setter. */

package main.java.org.example;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class GreetingCollector {
    private Greeting greeting;

    /* This is how you do setter injection */
    @Autowired
    public void setGreeting(Greeting greeting) {
        this.greeting = greeting;
    }

    public String getGreeting() {
        return greeting.getGreeting();
    }
}


/* This is a minimal config class. 
@ComponentScan instructs to look for classes that are 
annotated with @Component annotation (in other words, beans) */

package main.java.org.example;    
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@ComponentScan
@Configuration
public class Config {}

If you want to do it explicitly:

package main.java.org.example;  
import main.java.org.example.GreetingCollector;
import main.java.org.example.Greeting;  
import org.springframework.context.annotation.Configuration;

@Configuration
public class Config {
    @Bean
    public Greeting greeting() {
        return new Greeting();
    }

    @Bean
    public GreetingCollector greetingCollector(Greeting greeting) {
        return new GreetingCollector(greeting);
    }
}

And if you want to run it just to see how it works:

import main.java.org.example.Config;
import main.java.org.example.GreetingCollector;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class AppContext {
    public static void main(String args[]) {
        System.out.println("Configuring application context...");
        ApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
        GreetingCollector collector = (GreetingCollector) context.getBean("greetingCollector");
        System.out.println(collector.getGreeting());
    }
}

Naturally, Spring web application would be a bit different, but the basic injection idea is the same. First, you need to declare beans (either by using @Bean, @Component or any other annotation: see here and here for differences). You annotate either a setter or constructor (or even a field) with @Autowired, specify parameters (which do not necessarily need to be concrete classes - interfaces, abstract classes are fine, too), assign them to appropriate fields. Create a config class which takes cares of bean instantiation. You do not need to have your components in the same folder as config classes, as you can always specify where to look for components. Finally, if you want a more fine grained control, you can always declare beans explicitly in configuration class (so called JavaConfig, whereas @ComponentScan based config might sometimes be called autoconfig). This should be enough to get you started and give you vocabulary to search for more advanced stuff.

And of course, with Spring Boot everything is even more abstracted away/quicker.

like image 196
cegas Avatar answered Oct 16 '22 13:10

cegas


However, I was told that xml is deprecated and all new applications should be done with java configuration

XML is not deprecated but annotations are there which makes life easy. Then why to go for plain old XML. Remember "Convention over Configuration"

Where should I be declaring the bean and how would I do it?

I think you should search google for annotations like @Component, @Configuration, @Bean. Read about them you'll understand

This is one of the examples I have seen, yet it is implemented with xml.

You would find many example implemented using XML as XML was widely used in earlier days of Spring. Now with the advent of Spring 4 and Spring Boot. Most of the developers don't use XML on a large scale.

like image 1
BeginnersSake Avatar answered Oct 16 '22 14:10

BeginnersSake