依赖查找
历史
单一类型依赖查找
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名称和类型查找
1 2 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
1 2 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()
1 2 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 |
是 |
1 2 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 的线程安全性