Spring boot中查找bean有多种方式,目前我了解到的有以下五种。按照返回结果来分类,可以分成查找单个bean和bean 集合两大类, 按照查找是否安全来分类, 可以分成安全查找和非安全查找。
返回结果 | 是否安全 | 代码 |
---|---|---|
单个bean | 否 | BeanFactory.getBean() |
单个bean | 否 | ObjectProvider.getObject() |
单个bean | 是 | ObjectProvider.getIfAvailable() |
集合bean | 是 | ListableBeanFactory.getBeansOfType() |
集合bean | 是 | ObjectProvider.stream |
下面将以上五种方式的代码呈现给大家
- BeanFactory.getBean 是最容易想到的一种查找bean的方式, 但是这种方式是非常不安全的。 如果没有找到符合要求的bean, 就会throw NoSuchBeanDefinitionException。 如果找到多个符合要求的bean, 就会throw NoUniqueBeanDefinitionException。
private static void lookupByBeanFactoryGetBean(BeanFactory beanFactory) {
commonRunLookupJob(() -> {
beanFactory.getBean(String.class);
});
}
private static void commonRunLookupJob(Runnable runnable) {
try {
runnable.run();
} catch (BeansException exception) {
exception.printStackTrace();
}
}
}
- ObjectProvider.getObject。 ObjectProvider 是spring4.3开始新加的一个类, 继承自ObjectFactory。
private static void lookupByObjectProviderGetObject(BeanFactory beanFactory) {
ObjectProvider<String> beanProvider = beanFactory.getBeanProvider(String.class);
commonRunLookupJob(() -> {
beanProvider.getObject();
});
}
3.ObjectProvider.getIfAvailable. 顾名思义, 就是如果有符合要求的bean的时候, 才会返回, 否则就返回null。 但是大家注意, 这个方法并不是说就不会throw BeansException了。 如果查找的是个lazy 初始化的bean,在调用这个方法的时候才会去create bean, 所以如果在create的时候就有问题, 还是会throw BeansException的。
private static void lookupByObjectProviderGetIfAvailable(BeanFactory beanFactory) {
ObjectProvider<String> beanProvider = beanFactory.getBeanProvider(String.class);
commonRunLookupJob(() -> {
beanProvider.getIfAvailable();
});
}
- ListableBeanFactory.getBeansOfType 返回的是一个以bean 名字作为key的Map
private static void lookupByListableBeanFactoryGetBeansOfType(ListableBeanFactory beanFactory) {
commonRunLookupJob(() -> {
beanFactory.getBeansOfType(String.class);
});
}
- BeanProvider 同时也继承自Iterable 接口, 所以也支持stream。
private static void lookupByObjectProviderStream(BeanFactory beanFactory) {
ObjectProvider<String> beanProvider = beanFactory.getBeanProvider(String.class);
commonRunLookupJob(() -> {
beanProvider.stream().forEach(System.out::println);
});
}
以下附录是完整的demo 代码
package com.matthew.bayi.lookup;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Lazy;
public class BeanLookupDemo {
public static void main(String[] args) {
// create application context
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// register configuration class
applicationContext.register(BeanLookupDemo.class);
// start application context
applicationContext.refresh();
// loop up by beanfactory getbean
lookupByBeanFactoryGetBean(applicationContext);
// loop up by ObjectProvider GetObject
lookupByObjectProviderGetObject(applicationContext);
// loop up by ObjectProvider getIfAvailable
lookupByObjectProviderGetIfAvailable(applicationContext);
// look up by ListableBeanFactory GetBeansOfType
lookupByListableBeanFactoryGetBeansOfType(applicationContext);
// look up by ObjectProvider Stream
lookupByObjectProviderStream(applicationContext);
// close application context
applicationContext.close();
}
@Bean
@Lazy
String helloWorld(){
// throw new RuntimeException("Error Create bean");
return "Hello";
}
private static void lookupByBeanFactoryGetBean(BeanFactory beanFactory) {
commonRunLookupJob(() -> {
beanFactory.getBean(String.class);
});
}
private static void lookupByObjectProviderGetObject(BeanFactory beanFactory) {
ObjectProvider<String> beanProvider = beanFactory.getBeanProvider(String.class);
commonRunLookupJob(() -> {
beanProvider.getObject();
});
}
private static void lookupByObjectProviderGetIfAvailable(BeanFactory beanFactory) {
ObjectProvider<String> beanProvider = beanFactory.getBeanProvider(String.class);
commonRunLookupJob(() -> {
beanProvider.getIfAvailable();
});
}
private static void lookupByListableBeanFactoryGetBeansOfType(ListableBeanFactory beanFactory) {
commonRunLookupJob(() -> {
beanFactory.getBeansOfType(String.class);
});
}
private static void lookupByObjectProviderStream(BeanFactory beanFactory) {
ObjectProvider<String> beanProvider = beanFactory.getBeanProvider(String.class);
commonRunLookupJob(() -> {
beanProvider.stream().forEach(System.out::println);
});
}
private static void commonRunLookupJob(Runnable runnable) {
try {
runnable.run();
} catch (BeansException exception) {
exception.printStackTrace();
}
}
}