Hier ist mein 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>
Warum funktioniert das nicht? Ich verstehe NullPointerException
. Ist es möglich, Autowiring in einer eigenständigen Anwendung zu verwenden?
Antworten:
Der Frühling funktioniert in einer eigenständigen Anwendung. Sie verwenden den falschen Weg, um eine Frühlingsbohne zu erstellen. Der richtige Weg, es so zu machen:
@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"; } }
Im ersten Fall (dem in der Frage) erstellen Sie das Objekt selbst, anstatt es aus dem Spring-Kontext abzurufen. Spring bekommt also keine Chance auf
Autowire
die Abhängigkeiten (was die verursachtNullPointerException
).Im zweiten Fall (der in dieser Antwort) erhalten Sie die Bohne aus dem Spring-Kontext und daher wird sie von Spring verwaltet und Spring kümmert sich darum
autowiring
.quelle
new ArrayList()
beispielsweise jemals anrufen können? Wenn Sie eine Klasse mit automatisch verdrahteten Parametern haben und diese mitnew
instanziieren, findet die automatische Verdrahtung nicht statt.<context:annotation-config /> <context:component-scan base-package="com.yourcompany.mycomponents" />
Spring entfernt sich von XML-Dateien und verwendet häufig Anmerkungen. Das folgende Beispiel ist eine einfache eigenständige Spring-Anwendung, die anstelle von XML-Dateien Anmerkungen verwendet.
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; } }
Dies ist eine einfache Bohne. Es ist mit der
@Component
Anmerkung zur automatischen Erkennung durch den Spring-Container verziert .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()); } }
Dies ist die Hauptklasse
Application
. Die@ComponentScan
Anmerkung sucht nach Komponenten. Die@Autowired
Annotation fügt die Bean in diemessage
Variable ein. MitAnnotationConfigApplicationContext
wird der Spring-Anwendungskontext erstellt.Mein Standalone Spring-Tutorial zeigt, wie Sie eine Standalone Spring-Anwendung mit XML und Anmerkungen erstellen.
quelle
Für Spring 4 können wir mit Spring Boot das folgende Beispiel verwenden, ohne das Anti-Pattern zu verwenden, die Bean direkt aus dem ApplicationContext abzurufen:
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
Stellen Sie sicher, dass sich alle Ihre injizierten Dienste unter oder unter den Unterpaketen befinden.quelle
Wenn Sie SpringBoot ausführen:
Ich hatte nur das gleiche Problem, dass ich einen meiner Dienste mit der statischen Hauptmethode nicht automatisch verdrahten konnte.
Im Folgenden finden Sie einen Ansatz für den Fall, dass Sie sich auf SpringApplication.run verlassen :
@SpringBootApplication public class PricingOnlineApplication { @Autowired OrchestratorService orchestratorService; public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(PricingOnlineApplication.class, args); PricingOnlineApplication application = context.getBean(PricingOnlineApplication.class); application.start(); } private void start() { orchestratorService.performPricingRequest(null); } }
Ich habe festgestellt, dass SpringApplication.run einen Kontext zurückgibt, der ähnlich wie die oben beschriebenen Ansätze verwendet werden kann. Von dort ist es genau das gleiche wie oben ;-)
quelle
Eine schöne Lösung wäre, folgendes zu tun:
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; } }
Dann können Sie es wie folgt verwenden:
Ich fand diese sehr schöne Lösung auf der folgenden Website: https://confluence.jaytaala.com/pages/viewpage.action?pageId=18579463
quelle