Использование 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
. Можно ли использовать автоуправление в автономном приложении?
Ответы
Ответ 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