依赖查找

历史

单一类型依赖查找

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名称和类型查找
      • getBean(String,Class);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* 通过 {@link org.springframework.beans.factory.ObjectProvider} 进行依赖查找
*/
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名称查找
      • 基于containsLocalBean方法实现
    • 根据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"); //false
displayContainsLocalBean(parentBeanFactory, "user"); //true

displayContainsBean(beanFactory, "user"); //true
displayContainsBean(parentBeanFactory,"user");//true

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
/**
* 通过 {@link org.springframework.beans.factory.ObjectProvider} 进行依赖查找
*/
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);
// Iterator<String> iterator = objectProvider.iterator();
// while(iterator.hasNext()){
// System.out.println(iterator.next());
// }
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事件广播器
  • 注解驱动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 的线程安全性