Подтвердить что ты не робот

Использование autwire Spring 3 в автономном приложении Java

Вот мой код:

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>

Почему это не работает? Я получаю NullPointerException. Можно ли использовать автоуправление в автономном приложении?

4b9b3361

Ответ 1

Spring работает в автономном приложении. Вы используете неправильный способ создания spring bean. Правильный способ сделать это следующим образом:

@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";
    }
}

В первом случае (в вопросе) вы сами создаете объект, а не получаете его из контекста spring. Таким образом, spring не получает возможность Autowire зависимостей (что вызывает NullPointerException).

Во втором случае (в этом ответе) вы получаете bean из контекста spring и, следовательно, управляется spring, а spring заботится о autowiring.

Ответ 2

Spring отходит от файлов XML и сильно использует аннотации. Следующий пример представляет собой простое автономное приложение Spring, которое использует аннотацию вместо 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;
   }
}

Это простой bean. Он украшен аннотацией @Component для автоматического обнаружения контейнером 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());
    }
}

Это основной класс Application. Аннотация @ComponentScan ищет компоненты. Аннотация @Autowired вводит bean в переменную message. AnnotationConfigApplicationContext используется для создания контекста приложения Spring.

My Автономный Spring учебник показывает, как создать автономное приложение Spring с XML и аннотациями.

Ответ 3

Для Spring 4, используя Spring Boot, мы можем иметь следующий пример, не используя анти-шаблон для непосредственного получения Bean из 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";
    }
}

Убедитесь, что все ваши внедренные службы находятся под com.yourproject или его подпакетами.

Ответ 4

Хорошим решением было бы сделать следующее,

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class SpringContext implements ApplicationContextAware {

private static ApplicationContext context;

/**
 * Returns the Spring managed bean instance of the given class type if it exists.
 * Returns null otherwise.
 * @param beanClass
 * @return
 */
public static <T extends Object> T getBean(Class<T> beanClass) {
    return context.getBean(beanClass);
}

@Override
public void setApplicationContext(ApplicationContext context) throws BeansException {

    // store ApplicationContext reference to access required beans later on
    SpringContext.context = context;
}
}

Тогда вы можете использовать его как:

YourClass yourClass = SpringContext.getBean(YourClass.class);

Я нашел это очень хорошее решение на следующем веб-сайте: https://confluence.jaytaala.com/pages/viewpage.action?pageId=18579463