在独立 Java 应用程序中使用 Spring3自动连接

这是我的代码:

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。可以在绿色软体中使用自动装配吗?

102840 次浏览

斯普林在绿色软体工作。你用错误的方法创建了一个春天的豆子。正确的做法是:

@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

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 应用程序上下文。

我的 独立的 Spring 教程展示了如何使用 XML 和注释创建一个独立的 Spring 应用程序。

对于 Spring 4,使用 Spring Boot 我们可以得到以下示例,而不必使用直接从 ApplicationContext 获取 Bean 的反模式:

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或其子包之下。

一个不错的解决办法是这样做,

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

如果你正在运行 SpringBoot:

我只是有同样的问题,我不能自动从静态主方法的服务之一。

如果你依赖于 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 返回一个上下文,可以使用类似于上面描述的方法。从那里开始,它和上面的完全一样; -)