目录

概览

一:单一类型查找(BeanFactory)

二:集合类型依赖查找 - ListableBeanFactory

三:层次性依赖查找 - HierarchicalBeanFactory

四:Bean 延迟依赖查找接口

五:安全依赖查找

六:内建可查找依赖


概览

书接上回,IOC示例,在原有基础上详细罗列分析spring依赖查找的类型及范围,spring大致可以分为以下多种查找类型:

  1. 单一类型的依赖查找
  2. 集合类型的依赖查找
  3. 层次性依赖查找
  4. 延迟依赖查找
  5. 安全依赖查找
  6. 内建可查找的依赖

一:单一类型查找(BeanFactory)

  • 根据名称:
  1.         getBean(String)
  2.         getBean(String,Object...)  2.5-
  • 根据Bean类型:
  •         事实查找
  1.                 getBean(Class)  --- 3.0
  2.                 getBean(Class,Object...)  --- 4.1
  •         延迟查找  --- 5.1
  1.                 getBeanProvider(Class)
  2. ResolvableType)
  • 根据 Bean 名称 + 类型查找:
  1.         getBean(String,Class)

单一类型比较简单,这里举例延迟查找类型

public class ObjectProviderDemo {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
        ctx.register(ObjectProviderDemo.class);
        ctx.refresh();
        ObjectProvider<String> beanProvider = ctx.getBeanProvider(String.class);
        String object = beanProvider.getObject();
        System.out.println(object);
    }
    @Bean
    @Primary
    public String hello() {
        return "hello";
    }
    @Bean
    public String world() {
        return "world";
    }
}

这里最终输出字符串“hello”,因为hello上加了@Primary注解

而getBeanProvider()的实现也是对实时查找的一层封装,DefaultListableBeanFactory部分源码:

public <T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType) {
	return new BeanObjectProvider<T>() {
		@Override
		public T getObject() throws BeansException {
			T resolved = resolveBean(requiredType, null, false);
			if (resolved == null) {
				throw new NoSuchBeanDefinitionException(requiredType);
			}
			return resolved;
		}
		@Override
		public T getObject(Object... args) throws BeansException {
			T resolved = resolveBean(requiredType, args, false);
			if (resolved == null) {
				throw new NoSuchBeanDefinitionException(requiredType);
			}
			return resolved;
		}
		@Override
		@Nullable
		public T getIfAvailable() throws BeansException {
			return resolveBean(requiredType, null, false);
		}
		...
	};
}

BeanObjectProvider的定义在DefaultListableBeanFactory中,而resolveBean()就是实时查找的方法,这里类似于Future体系中的Promise角色。

private interface BeanObjectProvider<T> extends ObjectProvider<T>, Serializable {
}

二:集合类型依赖查找 - ListableBeanFactory

  • 根据 Bean 类型查找
  • 根据类型查找名称列表
  • getBeanNamesForType(Class)
  • getBeanNamesForType(ResolveType)
  • 根据类型查找Bean列表
  • getBeansOfType(Class)
  • 通过注解类型查找 -- 3.0(jdk5)
  • getBeanNamesForAnnotation(Class<? extends Annotation>)
  • getBeansWithAnnotation(Class<? extends Annotation>)
  • findAnnotationOnBean(String beanName,Class<? extends Annotation>)

根据类型或则根据注解查找在平时开发中使用也是比较广泛,这里就不举例说明了。

三:层次性依赖查找 - HierarchicalBeanFactory

双亲BeanFactory:getParentBeanFactory()

层次性查找

  • containsLocalBean()方法实现
  • 单一类型:BeanFactoryUtils#beanOfType()
  • 集合类型:BeanFactoryUtils#beansOfTypeIncloudingAncestors()
  • BeanUitls#beanNamesForTypeIncludingAncestors()

示例:

public class HierarchicalBeanFactoryDemo {

    public static void main(String[] args) {
        //parent
        AnnotationConfigApplicationContext parentCtx = new AnnotationConfigApplicationContext();
        parentCtx.register(ParentConf.class);
        parentCtx.refresh();
        //child
        AnnotationConfigApplicationContext childCtx = new AnnotationConfigApplicationContext();
        childCtx.setParent(parentCtx);
        childCtx.register(ChildConf.class);
        childCtx.refresh();

        //test
        Object hello = childCtx.getBean("hello");
        Object world = childCtx.getBean("world");
        System.out.println(hello); //hello-child
        System.out.println(world); //world-parent

        System.out.println(childCtx.containsLocalBean("hello"));//true
        System.out.println(childCtx.containsLocalBean("world"));//false

        //list  仅会在子类中查找
        Map<String, String> beansOfType = childCtx.getBeansOfType(String.class);//{hello=hello-child}
        System.out.println(beansOfType);
        Map<String, Pig> pigs = childCtx.getBeansOfType(Pig.class);
        System.out.println(pigs);//{}

        //会包含父容器中bean  输出:{hello=hello-child, world=world-parent}
        Map<String, String> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(childCtx, String.class);
        System.out.println(beans);

        //输出:[hello, world]
        String[] names = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(childCtx, String.class);
        System.out.println(Arrays.toString(names));
        //close
        childCtx.close();
    }

    public static class ParentConf {
        @Bean
        public String hello() {
            return "hello-parent";
        }

        @Bean
        public String world() {
            return "world-parent";
        }

        @Bean
        public Pig pig() {
            return new Pig();
        }
    }

    public static class ChildConf {
        @Bean
        public String hello() {
            return "hello-child";
        }
    }
}

可见当从子类中查找不到时,会继续迭代在父类容器中继续查找,在FeignClient中就用到了父子容器的实现方式。

同时需要留意的是ListableBeanFactory#beansOfType(Class)只会在当前容器中查找。

四:Bean 延迟依赖查找接口

  • org.springframework.beans.factory.ObjectFactory
  • org.springframework.beans.factory.ObjectProvider
  • Spring 5 对 Java 8 特性扩展
  • 函数式接口

                        getIfAvailable(Supplier)



                        ifAvailable(Consumer)



                        Stream 扩展 - stream()


在单一类型查找中我们讨论了延迟查找的能力,这里仅列出,就不在赘述。

五:安全依赖查找

spring查找匹配文件名文件 spring依赖查找_spring

六:内建可查找依赖

AbstractApplicationContext内建可查找依赖

spring查找匹配文件名文件 spring依赖查找_ioc_02

注解驱动Spring应用上下文内建可查找依赖

spring查找匹配文件名文件 spring依赖查找_spring查找匹配文件名文件_03

依赖查找中的常见异常:BeansException的子类型

spring查找匹配文件名文件 spring依赖查找_java_04