在 Spring 引导中检索 bean?
Retrieving beans in Spring Boot?
我过去曾使用旧版 Spring。我们通过 xml 配置定义我们的 beans 并手动连接它们。我的团队终于齐心协力更新注释并使用 Spring Boot 而不是 Spring MVC 的 'traditional' 方法。
话虽如此,我不知道我到底是如何在 Boot 中检索 bean 的。在传统中,Spring 要么使用 constructor/setter 注入(取决于我们的配置),要么我们可以直接使用 context.getBean("myBeanID");
调用 bean 但是,现在情况似乎不再如此。
我整理了一个小测试用例来尝试在下面的代码中让它工作:
package com.ots;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
public class GriefUIApplication{
public static void main(String[] args) {
SpringApplication.run(GriefUIApplication.class, args);
SessionFactory factory = new Configuration().configure("hibernate.cfg.xml")
.addAnnotatedClass(GriefRecord.class).addAnnotatedClass(RecordId.class)
.addAnnotatedClass(CrossReferenceRecord.class)
.buildSessionFactory();
Statics.setSessionFactory(factory);
TennisCoach tCoach = new TennisCoach();
tCoach.getCoach();
}
}
interface Coach{
public String workout();
}
@Service
class TennisCoach implements Coach{
private Coach soccerCoach;
@Autowired
private ApplicationContext context;
public TennisCoach() {
}
public Coach getCoach() {
System.out.println(context + " IS THE VALUE OF THE CONTEXT OBJECT");
soccerCoach = (SoccerCoach)context.getBean("soccerCoach");
System.out.println(soccerCoach.getClass());
return soccerCoach;
}
@Override
public String workout() {
String practice = "practice your backhand!";
System.out.println(practice);
return practice;
}
}
@Service
class SoccerCoach implements Coach{
public SoccerCoach() {
}
@Override
public String workout() {
String practice = "practice your footwork!";
System.out.println(practice);
return practice;
}
}
@RestController
class MyController{
@GetMapping("/")
public String sayHello() {
return "Time on server is: " + new java.util.Date();
}
}
我尝试将 ApplicationContext 对象自动装配到 TennisCoach class。当我 运行 this 时,那个对象为空。
我们如何在 Boot 中检索 bean?
最常见的方法是使用 @Autowired
注释。另外,因为你有两个不同的 Coach
接口实现,你应该使用 @Qualifier
注释来告诉 Spring 要注入哪个接口实现。
关于这两个注释的一些教程,以帮助您入门:
对于您的示例,要将 bean 注入您的控制器,您应该这样做:
@RestController
class MyController {
@Autowired
@Qualifier("soccerCoach")
private Coach coach;
@GetMapping("/")
public String sayHello() {
// this should invoke the workout() from SoccerCoach implementation
System.out.println(coach.workout());
return "Time on server is: " + new java.util.Date();
}
}
或者,如您所愿,使用构造函数注入将 soccerCoach
注入 tennisCoach
,代码将变为:
@Service
class TennisCoach implements Coach {
private Coach soccerCoach;
@Autowired
public TennisCoach(@Qualifier("soccerCoach") Coach soccerCoach) {
this.soccerCoach = soccerCoach;
}
public Coach getCoach() {
System.out.println(soccerCoach.getClass());
return soccerCoach;
}
}
如果您确实需要使用 ApplicationContext
来检索一些 bean,那么在具有 main
功能的 class 中这样做是不可取的。只需创建另一个 bean(您可以使用 @Componenent
注释)。这是一个例子:
@Component
public class AnyComponent {
@Autowired
private ApplicationContext applicationContext;
public void invokeCoach() {
System.out.println(applicationContext.getBean("tennisCoach"));
System.out.println(applicationContext.getBean(SoccerCoach.class));
}
}
并在您的应用程序流中注入这个 bean,可以在控制器、服务或存储库中:
@RestController
class MyController {
@Autowired
private AnyComponent anyComponent;
@GetMapping("/")
public String sayHello() {
anyComponent.invokeCoach();
return "Time on server is: " + new java.util.Date();
}
}
注意:通过注解注入 bean 是 Spring 特有的东西,一般来说,不是 Spring Boot 特有的东西。
来自 https://www.baeldung.com/spring-autowire:
Starting with Spring 2.5, the framework introduced a new style of Dependency Injection driven by @Autowired Annotations. This annotation allows Spring to resolve and inject collaborating beans into your bean.
直接注入需要的bean。 Spring 引导中不需要 ApplicationContext
。
@Service
class TennisCoach {
private SoccerCoach soccerCoach;
@Autowired
public TennisCoach(SoccerCoach soccerCoach) {
this.soccerCoach = soccerCoach;
}
}
我过去曾使用旧版 Spring。我们通过 xml 配置定义我们的 beans 并手动连接它们。我的团队终于齐心协力更新注释并使用 Spring Boot 而不是 Spring MVC 的 'traditional' 方法。
话虽如此,我不知道我到底是如何在 Boot 中检索 bean 的。在传统中,Spring 要么使用 constructor/setter 注入(取决于我们的配置),要么我们可以直接使用 context.getBean("myBeanID");
调用 bean 但是,现在情况似乎不再如此。
我整理了一个小测试用例来尝试在下面的代码中让它工作:
package com.ots;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
public class GriefUIApplication{
public static void main(String[] args) {
SpringApplication.run(GriefUIApplication.class, args);
SessionFactory factory = new Configuration().configure("hibernate.cfg.xml")
.addAnnotatedClass(GriefRecord.class).addAnnotatedClass(RecordId.class)
.addAnnotatedClass(CrossReferenceRecord.class)
.buildSessionFactory();
Statics.setSessionFactory(factory);
TennisCoach tCoach = new TennisCoach();
tCoach.getCoach();
}
}
interface Coach{
public String workout();
}
@Service
class TennisCoach implements Coach{
private Coach soccerCoach;
@Autowired
private ApplicationContext context;
public TennisCoach() {
}
public Coach getCoach() {
System.out.println(context + " IS THE VALUE OF THE CONTEXT OBJECT");
soccerCoach = (SoccerCoach)context.getBean("soccerCoach");
System.out.println(soccerCoach.getClass());
return soccerCoach;
}
@Override
public String workout() {
String practice = "practice your backhand!";
System.out.println(practice);
return practice;
}
}
@Service
class SoccerCoach implements Coach{
public SoccerCoach() {
}
@Override
public String workout() {
String practice = "practice your footwork!";
System.out.println(practice);
return practice;
}
}
@RestController
class MyController{
@GetMapping("/")
public String sayHello() {
return "Time on server is: " + new java.util.Date();
}
}
我尝试将 ApplicationContext 对象自动装配到 TennisCoach class。当我 运行 this 时,那个对象为空。
我们如何在 Boot 中检索 bean?
最常见的方法是使用 @Autowired
注释。另外,因为你有两个不同的 Coach
接口实现,你应该使用 @Qualifier
注释来告诉 Spring 要注入哪个接口实现。
关于这两个注释的一些教程,以帮助您入门:
对于您的示例,要将 bean 注入您的控制器,您应该这样做:
@RestController
class MyController {
@Autowired
@Qualifier("soccerCoach")
private Coach coach;
@GetMapping("/")
public String sayHello() {
// this should invoke the workout() from SoccerCoach implementation
System.out.println(coach.workout());
return "Time on server is: " + new java.util.Date();
}
}
或者,如您所愿,使用构造函数注入将 soccerCoach
注入 tennisCoach
,代码将变为:
@Service
class TennisCoach implements Coach {
private Coach soccerCoach;
@Autowired
public TennisCoach(@Qualifier("soccerCoach") Coach soccerCoach) {
this.soccerCoach = soccerCoach;
}
public Coach getCoach() {
System.out.println(soccerCoach.getClass());
return soccerCoach;
}
}
如果您确实需要使用 ApplicationContext
来检索一些 bean,那么在具有 main
功能的 class 中这样做是不可取的。只需创建另一个 bean(您可以使用 @Componenent
注释)。这是一个例子:
@Component
public class AnyComponent {
@Autowired
private ApplicationContext applicationContext;
public void invokeCoach() {
System.out.println(applicationContext.getBean("tennisCoach"));
System.out.println(applicationContext.getBean(SoccerCoach.class));
}
}
并在您的应用程序流中注入这个 bean,可以在控制器、服务或存储库中:
@RestController
class MyController {
@Autowired
private AnyComponent anyComponent;
@GetMapping("/")
public String sayHello() {
anyComponent.invokeCoach();
return "Time on server is: " + new java.util.Date();
}
}
注意:通过注解注入 bean 是 Spring 特有的东西,一般来说,不是 Spring Boot 特有的东西。
来自 https://www.baeldung.com/spring-autowire:
Starting with Spring 2.5, the framework introduced a new style of Dependency Injection driven by @Autowired Annotations. This annotation allows Spring to resolve and inject collaborating beans into your bean.
直接注入需要的bean。 Spring 引导中不需要 ApplicationContext
。
@Service
class TennisCoach {
private SoccerCoach soccerCoach;
@Autowired
public TennisCoach(SoccerCoach soccerCoach) {
this.soccerCoach = soccerCoach;
}
}