从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

相关文章
相关标签/搜索