從Spring 應用上下文獲取 Bean 的經常使用姿式

1. 前言

一般,在Spring應用程序中,當咱們使用 @Bean@Service@Controller@Configuration 或者其它特定的註解將 Bean 注入 Spring IoC 。而後咱們可使用 Spring 框架提供的 @Autowired 或者 JSR250JSR330 規範註解來使用由 Spring IoC 管理的 Beanhtml

2. 從應用程序上下文中獲取 Bean

今天咱們未來學習如何從 ApplicationContext 中獲取 Bean 。由於有些狀況下咱們不得不從應用程序上下文中來獲取 Beanjava

2.1 獲取全部的 Bean

ApplicationContext 提供了獲取全部已經成功注入 Spring IoC 容器的 Bean 名稱的方法 getBeanDefinitionNames() 。而後咱們能夠藉助於其 getBean(String name) 方法使用 Bean 名稱獲取特定的 Bean。 咱們使用以前文章中介紹的 CommandLineRunner 接口來打印一下結果。web

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);
         });
 
     }
 }

運行應用會輸出:spring

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

從上面打印的信息咱們也能看出來一些端倪。springboot

  • 有的 beanName 是類全限定名。
  • @Component@Repository@Service@Controller等註解建立 Bean 時,若是不指定bean名稱,名稱的默認規則是類名的首字母小寫,如 cn.felord.war.controller.FooControllerfooController。若是類名前兩個或以上個字母都是大寫,那麼名稱與類名同樣,如 cn.felord.war.controller.IServiceImplIServiceImpl
  • @Bean 標識的 Bean 默認 爲方法名稱。
  • 配置類相關注解 @Configuration 通常使用類全限定名。

可是請注意:若是你在聲明 Bean 的時候指定了名稱就只是你指定的名稱 。若是咱們熟悉這些規則,使用上面提到的getBean(String name) 方法不失爲一種好辦法。app

2.3 經過類型來獲取 Bean

若是咱們不清楚咱們想要的特定類型 Bean 的名稱,咱們能夠根據類型來獲取 BeanApplicationContext 提供了能夠加載特定類型的 Bean 的全部 Bean 的方法getBeansOfType()。它將返回 Map <String,Object> 其中鍵是 Bean 名稱,而值是 Bean 的實際對象。框架

咱們修改 2.1 章節 例子中的 run 方法:ide

@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);
         });
     }

再次運行,控制檯打印出:spring-boot

beanName : fooController
 bean : cn.felord.war.controller.FooController@545f80bf

2.4 獲取特定 Bean 聲明註解標記的 Bean

ApplicationContextgetBeansWithAnnotation() 方法可讓咱們獲取 @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 Actuatorbeans 端點來獲取全部的 Bean 信息。

關注公衆號:Felordcn 獲取更多資訊

我的博客:https://felord.cn

相關文章
相關標籤/搜索