依赖查找
历史
单一类型依赖查找
JNDI - javax.naming.Context#lookup*(javax.naming.Name);
JavaBeans - java.beans.beancontext.BeanContext
- BeanFactory:
- 根据bean名称查找
- getBean(String);
- getBean(String,Object…) //覆盖默认参数
 
- 根据Bean类型查找
- bean实时查找
- getBean(Class)
- getBean(Class,Object…)//覆盖默认参数
 
- bean延时查找
- getBeanProvider(Class);
- getBeanProvider(String,Class); 
 
 
- 根据Bean名称和类型查找
 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 
 | 
 
 public class ObjectProviderDemo {
 public static void main(String[] args) {
 AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
 applicationContext.register(ObjectProviderDemo.class);
 applicationContext.refresh();
 lookupByObjectProvider(applicationContext);
 applicationContext.close();
 }
 
 @Bean
 public String helloWorld() {
 return "Hello World";
 }
 private static void lookupByObjectProvider(AnnotationConfigApplicationContext applicationContext) {
 ObjectProvider<String> objectProvider = applicationContext.getBeanProvider(String.class);
 System.out.println(objectProvider.getObject());
 }
 }
 
 | 
集合类型依赖查找
java.beans.beancontext.BeanContext
ListableBeanFactory
是针对某个类型去查找一个集合列表。
一种是查询bean的名称, 一种是查询bean的实例。
一般情况下应该使用bean的名称来判断当前bean是否存在,或者进一步判断BeanDefinition是否存在。
而查询bean实例会提早初始化bean实例,造成初始化不完整。
- 根据Bean类型查找
- 获取同类型Bean名称列表
- getBeanNamesForType(Class)
- getBeanNamesForType(ResolvableType)
 
- 获取痛类型Bean实例列表
- getBeansOfType(Class)以及重载方法
 
 
- 根据注解类型查找
- 获取标注类型Bean 名称列表
- getBeanNamesForAnnotation(Class<? extends Annotation>);
 
- 获取标注类型Bean实例列表
- getBeansWithAnnotation(Class<? extends Annotation>);
 
- 获取指定名称+标注类型实例
- findAnnotationOnBean(String,Class<? extends Annotation>);
 
 
层次性依赖查找
java.beans.beancontext.BeanContext
HierachicalBeanFactory

- 双亲 BeanFactory: getParentBeanFactory();
- 层次查找
- 根据Bean名称查找
- 根据Bean类型查找实例列表
- 单一类型:BeanFactoryUtils#beanOfType
- 集合类型:BeanFactoryUtils#beansOfTypeIncludingAncestors
 
- 根据Java注解查找名称列表
- BeanFactoryUtils#beanNamesForTypeIncludingAncestors
 
 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 
 | public class HierarchicalDependencyLookupDemo {
 
 public static void main(String[] args) {
 AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
 
 ConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory();
 
 HierarchicalBeanFactory parentBeanFactory = createParentBeanFactory();
 
 beanFactory.setParentBeanFactory(parentBeanFactory);
 
 displayContainsLocalBean(beanFactory, "user");
 displayContainsLocalBean(parentBeanFactory, "user");
 
 displayContainsBean(beanFactory, "user");
 displayContainsBean(parentBeanFactory,"user");
 
 applicationContext.refresh();
 applicationContext.close();
 }
 
 
 private static void displayContainsBean(HierarchicalBeanFactory beanFactory, String beanName) {
 System.out.printf("当前 BeanFactory [%s] 是否包含  bean[name:%s]  %s\n", beanFactory, beanName, containsBean(beanFactory,beanName));
 
 }
 
 private static boolean containsBean(HierarchicalBeanFactory beanFactory, String beanName) {
 BeanFactory parentBeanFactory = beanFactory.getParentBeanFactory();
 if (parentBeanFactory instanceof HierarchicalBeanFactory) {
 HierarchicalBeanFactory parentHierarchicalBeanFactory = HierarchicalBeanFactory.class.cast(parentBeanFactory);
 if (containsBean(parentHierarchicalBeanFactory, beanName)) {
 return true;
 }
 }
 return beanFactory.containsLocalBean(beanName);
 }
 
 private static void displayContainsLocalBean(HierarchicalBeanFactory parentBeanFactory, String user) {
 System.out.printf("当前 BeanFactory [%s] 是否包含 Local bean[name:%s]  %s\n", parentBeanFactory, user, parentBeanFactory.containsLocalBean(user));
 }
 
 private static HierarchicalBeanFactory createParentBeanFactory() {
 DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
 XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
 String location = "classpath:applicationContext-lookup.xml";
 reader.loadBeanDefinitions(location);
 return beanFactory;
 }
 }
 
 | 
延迟依赖查找

- Bean延迟依赖查找接口
- org.springframework.beans.factory.ObjectFactory#getObject();
- org.springframework.beans.factory.ObjectProvider
- Spring5对于Java8的特性扩展
- 函数式接口
- getIfAvailable(Supplier)
- ifAvailable(Consumer)
 
- Stream扩展 - stream() 
 
 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 
 | 
 
 public class ObjectProviderDemo {
 
 
 public static void main(String[] args) {
 AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
 applicationContext.register(ObjectProviderDemo.class);
 applicationContext.refresh();
 
 lookupByObjectProvider(applicationContext);
 lookupIfAvailable(applicationContext);
 lookupByStream(applicationContext);
 applicationContext.close();
 }
 
 private static void lookupByStream(AnnotationConfigApplicationContext applicationContext) {
 ObjectProvider<String> objectProvider = applicationContext.getBeanProvider(String.class);
 
 
 
 
 objectProvider.stream().forEach(System.out::println);
 }
 
 private static void lookupIfAvailable(AnnotationConfigApplicationContext applicationContext) {
 ObjectProvider<User> userObjectProvider = applicationContext.getBeanProvider(User.class);
 User user = userObjectProvider.getIfAvailable(User::new);
 System.out.println(user);
 
 }
 
 @Bean
 @Primary
 public String helloWorld() {
 return "Hello World";
 }
 
 @Bean
 public String message(){
 return "message";
 }
 
 private static void lookupByObjectProvider(AnnotationConfigApplicationContext applicationContext) {
 ObjectProvider<String> objectProvider = applicationContext.getBeanProvider(String.class);
 System.out.println(objectProvider.getObject());
 }
 }
 
 | 
安全依赖查找
依赖查找安全性对比
| 依赖查找类型 | 代表实现 | 是否安全 | 
| 单一类型查找 | BeanFactory#getBean | 否 | 
|  | ObjectFactory#getObject | 否 | 
|  | ObjectProvider#getIfAvailable | 是 | 
| 集合类型查找 | ListableBeanFactory#getBeansOfType | 是 | 
|  | ObjectProvider.stream | 是 | 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 
 | import com.github.springframework.models.User;import org.springframework.beans.BeansException;
 import org.springframework.beans.factory.*;
 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 
 public class TypeSafetyDependencyLookupDemo {
 
 public static void main(String[] args) {
 AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
 applicationContext.register(TypeSafetyDependencyLookupDemo.class);
 applicationContext.refresh();
 
 displayBeanFactoryGetBean(applicationContext);
 displayObjectFactoryGetObject(applicationContext);
 displayObjectProviderIfAvailable(applicationContext);
 
 displayListableBeanFactoryGetBeansOfType(applicationContext);
 
 displayObjectProviderStreamOps(applicationContext);
 applicationContext.close();
 }
 
 public static void displayObjectProviderStreamOps(AnnotationConfigApplicationContext beanFactory){
 ObjectProvider<User> userObjectFactory = beanFactory.getBeanProvider(User.class);
 printException("displayObjectProviderStreamOps", ()->userObjectFactory.forEach(System.out::println));
 }
 
 public static void displayListableBeanFactoryGetBeansOfType(ListableBeanFactory beanFactory){
 printException("displayListableBeanFactoryGetBeansOfType", ()->beanFactory.getBeansOfType(User.class));
 }
 
 public static void displayObjectProviderIfAvailable(BeanFactory beanFactory){
 ObjectProvider<User> userObjectFactory = beanFactory.getBeanProvider(User.class);
 printException("displayObjectProviderIfAvailable", ()->userObjectFactory.getIfAvailable());
 }
 
 public static void displayObjectFactoryGetObject(BeanFactory beanFactory){
 ObjectProvider<User> userObjectFactory = beanFactory.getBeanProvider(User.class);
 printException("displayObjectFactoryGetObject", ()->userObjectFactory.getObject());
 }
 
 public static void displayBeanFactoryGetBean(BeanFactory beanFactory){
 printException("displayBeanFactoryGetBean",()->beanFactory.getBean(User.class));
 }
 
 public static void printException(String source, Runnable run){
 System.out.println("Source From : " + source);
 System.out.println("======================================");
 try{
 run.run();
 }catch (BeansException e){
 e.printStackTrace();
 }
 }
 }
 
 | 
内建可查找的依赖
- AbstractApplicationContext 内建可查找依赖
| Bean名称 | Bean实例 | 使用场景 | 
| environment | Environment对象 | 外部化配置以及Profiles | 
| systemProperties | java.util.Proerties对象 | Java系统属性 | 
| systemEnvironment | java.util.Map对象 | 操作系统环境变量 | 
| messageSource | MessageSource对象 | 国际化文案 | 
| lifecycleProcessor | LifecycleProcessor对象 | LifecycleBean处理器 | 
| applicationEventMulticaster | ApplicationEventMulticaster对象 | Spring事件广播器 | 
AnnotationConfigUtils.
| Bean名称 | Bean实例 | 使用场景 | 
| org.springframework.context.annotation.internalConfigurationAnnotationProcessor | ConfigurationClassPostProcessor对象 | 处理Spring配置类 | 
| org.springframework.context.annotation.internalAutowiredAnnotationProcessor | AutowireAnnotationBeanPostProcessor对象 | 处理@Autowired以及@Value注解 | 
| org.springframework.context.annotation.internalCommonAnnotatinProcessor | CommonAnnotationBeanPostProcessor对象 | 条件激活处理JSR-250注解,如@PostConstruct | 
| org.springframework.context.event.internalEventListenerProcessor | EventListenerMethodProcessor对象 | 处理@EventListener的Spring事件监听方法 | 
依赖查找中的异常
- NoSuchBeanDefinitionException
- NoUniqueBeanDefinitionException
- BeanInstantiationException
- BeanCreationException
- BeanDefinitionStoreException
常见题目
- ObjectFactory 和 BeanFactory 的区别
- BeanFactory.getBean 的线程安全性