这是我的代码:
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
。是否可以在独立应用程序中使用自动装配?
答案 0 :(得分:125)
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
)。
在第二种情况下(本答案中的那个),您从Spring上下文中获取bean,因此它是Spring管理的,Spring负责autowiring
。
答案 1 :(得分:20)
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应用程序上下文。
我的Standalone Spring tutorial展示了如何使用XML和注释创建独立的Spring应用程序。
答案 2 :(得分:7)
对于Spring 4,使用Spring Boot我们可以使用以下示例,而不使用直接从ApplicationContext获取Bean的反模式:
guard let spriteComponent = entity?.component(ofType: SpriteComponent.self) else {
return
}
确保所有注入的服务都在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";
}
}
或其子包下。
答案 3 :(得分:2)
如果您正在运行SpringBoot:
我遇到了同样的问题,无法通过静态main方法自动连接我的一项服务。
如果您依赖 SpringApplication.run ,请参见以下方法:
@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);
}
}
我注意到SpringApplication.run返回一个上下文,该上下文可以类似于上述方法使用。从那里开始,它与上面的完全相同;-)
答案 4 :(得分:0)
一个不错的解决方案是执行以下操作
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