web-dev-qa-db-fra.com

Utilisation de Spring 3 autowire dans une application autonome Java application

Voici mon code:

public class Main {

    public static void main(String[] args) {
        Main p = new Main();
        p.start(args);
    }

    @Autowired
    private MyBean myBean;
    private void start(String[] args) {
        ApplicationContext context = 
            new ClassPathXmlApplicationContext("META-INF/config.xml");
        System.out.println("my beans method: " + myBean.getStr());
    }
}

@Service 
public class MyBean {
    public String getStr() {
        return "string";
    }
}

<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-3.0.xsd
     http://www.springframework.org/schema/context
     http://www.springframework.org/schema/context/spring-context-3.0.xsd"> 
    <context:annotation-config /> 
    <context:component-scan base-package="mypackage"/>
</beans>

Pourquoi ça ne marche pas? Je reçois NullPointerException. Est-il possible d'utiliser l'auto-câblage dans une application autonome?

68
mike27

Spring fonctionne en application autonome. Vous utilisez la mauvaise façon de créer un haricot de printemps. La bonne façon de le faire comme ça:

@Component
public class Main {

    public static void main(String[] args) {
        ApplicationContext context = 
            new ClassPathXmlApplicationContext("META-INF/config.xml");

        Main p = context.getBean(Main.class);
        p.start(args);
    }

    @Autowired
    private MyBean myBean;
    private void start(String[] args) {
        System.out.println("my beans method: " + myBean.getStr());
    }
}

@Service 
public class MyBean {
    public String getStr() {
        return "string";
    }
}

Dans le premier cas (celui de la question), vous créez l'objet par vous-même, plutôt que de l'obtenir à partir du contexte Spring. Donc, Spring n'a pas l'occasion de Autowire les dépendances (ce qui cause le NullPointerException).

Dans le second cas (celui de cette réponse), vous obtenez le haricot du contexte Spring, qui est donc géré par Spring et Spring prend en charge autowiring.

127
Abhinav Sarkar

Spring s'éloigne des fichiers XML et utilise beaucoup les annotations. L'exemple suivant est une simple application Spring autonome qui utilise des annotations au lieu de fichiers XML.

package com.zetcode.bean;

import org.springframework.stereotype.Component;

@Component
public class Message {

   private String message = "Hello there!";

   public void setMessage(String message){

      this.message  = message;
   }

   public String getMessage(){

      return message;
   }
}

Ceci est un haricot simple. Il est décoré avec le @Component annotation pour la détection automatique par le conteneur Spring.

package com.zetcode.main;

import com.zetcode.bean.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;

@ComponentScan(basePackages = "com.zetcode")
public class Application {

    public static void main(String[] args) {

        ApplicationContext context
                = new AnnotationConfigApplicationContext(Application.class);

        Application p = context.getBean(Application.class);
        p.start();
    }

    @Autowired
    private Message message;
    private void start() {
        System.out.println("Message: " + message.getMessage());
    }
}

C'est la classe principale Application. Le @ComponentScan annotation recherche des composants. Le @Autowired annotation injecte le bean dans la variable message. Le AnnotationConfigApplicationContext est utilisé pour créer le contexte d'application Spring.

Mon tutoriel Spring autonome montre comment créer une application Spring autonome avec XML et des annotations.

20
Jan Bodnar

Pour Spring 4, en utilisant Spring Boot, nous pouvons avoir l'exemple suivant sans utiliser l'anti-pattern d'obtention directe du bean depuis ApplicationContext:

package com.yourproject;

@SpringBootApplication
public class TestBed implements CommandLineRunner {

    private MyService myService;

    @Autowired
    public TestBed(MyService myService){
        this.myService = myService;
    }

    public static void main(String... args) {
        SpringApplication.run(TestBed.class, args);
    }

    @Override
    public void run(String... strings) throws Exception {
        System.out.println("myService: " + MyService );
    }

}

@Service 
public class MyService{
    public String getSomething() {
        return "something";
    }
}

Assurez-vous que tous vos services injectés sont sous com.yourproject ou ses sous-packages.

10
Michail Michailidis