文章目錄
1. 前言
通常,在Spring應用程序中,當我們使用 @Bean
,@Service
,@Controller
,@Configuration
或者其它特定的注解將 Bean 注入 Spring IoC 。然后我們可以使用 Spring 框架提供的 @Autowired
或者 JSR250、JSR330 規范注解來使用由 Spring IoC 管理的 Bean 。
2. 從應用程序上下文中獲取 Bean
今天我們將來學習如何從 ApplicationContext
中獲取 Bean 。因為有些情況下我們不得不從應用程序上下文中來獲取 Bean 。
2.1 獲取所有的 Bean
ApplicationContext
提供了獲取所有已經成功注入 Spring IoC 容器的 Bean 名稱的方法 getBeanDefinitionNames()
。然后我們可以借助於其 getBean(String name)
方法使用 Bean 名稱獲取特定的 Bean。 我們使用之前文章中介紹的 CommandLineRunner
接口來打印一下結果。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import java.util.stream.Stream;
/** * @author Felordcn */
@SpringBootApplication
public class WarSpringBootApplication implements CommandLineRunner {
@Autowired
private ApplicationContext applicationContext;
public static void main(String[] args) {
SpringApplication.run(WarSpringBootApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
Stream.of(beanDefinitionNames).forEach(beanName->{
System.out.println("beanName : " beanName);
Object bean = applicationContext.getBean(beanName);
System.out.println("Spring bean : " bean);
});
}
}
運行應用會輸出:
2019-11-05 22:15:54.392 INFO 6356 --- [ main] cn.felord.war.WarSpringBootApplication : Started WarSpringBootApplication in 4.663 seconds (JVM running for 7.58)
beanName : org.springframework.context.annotation.internalConfigurationAnnotationProcessor
Spring bean : org.springframework.context.annotation.ConfigurationClassPostProcessor@6c44052e
beanName : org.springframework.context.annotation.internalAutowiredAnnotationProcessor
Spring bean : org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor@5c371e13
beanName : org.springframework.context.annotation.internalCommonAnnotationProcessor
Spring bean : org.springframework.context.annotation.CommonAnnotationBeanPostProcessor@530a8454
beanName : org.springframework.context.event.internalEventListenerProcessor
Spring bean : org.springframework.context.event.EventListenerMethodProcessor@1e34c607
beanName : org.springframework.context.event.internalEventListenerFactory
Spring bean : org.springframework.context.event.DefaultEventListenerFactory@5215cd9a
beanName : fooController
Spring bean : cn.felord.war.controller.FooController@31198ceb
beanName : IServiceImpl
Spring bean : cn.felord.war.controller.IServiceImpl@51671b08
<more...>
2.2 通過名稱獲取特定的 Bean
從上面打印的信息我們也能看出來一些端倪。
- 有的
beanName
是類全限定名。 @Component
、@Repository
、@Service
、@Controller
等注解創建 Bean 時,如果不指定bean名稱,名稱的默認規則是類名的首字母小寫,如cn.felord.war.controller.FooController
為fooController
。如果類名前兩個或以上個字母都是大寫,那么名稱與類名一樣,如cn.felord.war.controller.IServiceImpl
為IServiceImpl
@Bean
標識的 Bean 默認 為方法名稱。- 配置類相關注解
@Configuration
一般使用類全限定名。
但是請注意:如果你在聲明 Bean 的時候指定了名稱就只是你指定的名稱 。如果我們熟悉這些規則,使用上面提到的getBean(String name)
方法不失為一種好辦法。
2.3 通過類型來獲取 Bean
如果我們不清楚我們想要的特定類型 Bean 的名稱,我們可以根據類型來獲取 Bean 。ApplicationContext
提供了可以加載特定類型的 Bean 的所有 Bean 的方法getBeansOfType()
。它將返回 Map <String,Object>
其中鍵是 Bean 名稱,而值是 Bean
的實際對象。
我們修改 2.1 章節 例子中的 run
方法:
@Override
public void run(String... args) throws Exception {
Map<String, FooController> beansOfType = applicationContext.getBeansOfType(FooController.class);
beansOfType.forEach((beanName,bean)->{
System.out.println("beanName : " beanName);
System.out.println("bean : " bean);
});
}
再次運行,控制台打印出:
beanName : fooController
bean : cn.felord.war.controller.FooController@545f80bf
2.4 獲取特定 Bean 聲明注解標記的 Bean
ApplicationContext
的 getBeansWithAnnotation()
方法可以讓我們獲取 @Service
,@Controller
或任何其它可以用來創建 Bean 的注解創建的 Bean 。
@Override
public void run(String... args) throws Exception {
Map<String, Object> beansWithAnnotation = applicationContext.getBeansWithAnnotation(Controller.class);
beansWithAnnotation.forEach((beanName,bean)->{
System.out.println("beanName : " beanName);
System.out.println("bean : " bean);
});
}
打印出:
beanName : fooController
bean : cn.felord.war.controller.FooController@18ca3c62
beanName : basicErrorController
bean : org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController@2c0f7678
3. 總結
在本文中,我們學習如何從 Spring 應用上下文中獲取所有 Bean 的列表。有時我們需要檢查我們期望的 Bean 是否在 Spring 上下文中加載,或者我們需要檢查 Spring IoC 聲明的特定的 Bean 。當然你可以開啟Spring Boot Actuator 的 beans
端點來獲取所有的 Bean 信息。
關注公眾號:Felordcn獲取更多資訊