• 你不知道的Spring的依赖的查找和注入的来源


    1.写在前面

    前面的博客我们已经介绍完了spring的依赖的查找和注入的方式,这篇博客我们主要介绍下spring的依赖的查找和注入的来源。

    2.依赖查找的来源

    查找来源

    在这里插入图片描述

    Spring 內建 BeanDefintion

    在这里插入图片描述

    Spring 內建单例对象

    在这里插入图片描述

    上面的各种依赖都是在spring的生命周期的过程中,初始化的,这儿不做过多的赘述,后面的博客我们在详细的介绍。

    3.依赖注入的来源

    注入来源

    在这里插入图片描述

    具体的代码如下:

    package org.learn.spring.dependency.source;
    
    import org.springframework.beans.factory.BeanFactory;
    import org.springframework.beans.factory.BeanNameAware;
    import org.springframework.beans.factory.NoSuchBeanDefinitionException;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationEventPublisher;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.core.io.ResourceLoader;
    
    import javax.annotation.PostConstruct;
    
    // 依赖来源示例
    // BeanFactory.class ResourceLoader.class ApplicationEventPublisher.class ApplicationContext.class 不能用于我们的getBean
    public class DependencySourceDemo {
    
        // 注入在 postProcessProperties 方法执行,早于 setter注入 也早于生命周期回调函数@PostConstruct
        @Autowired
        private BeanFactory beanFactory;
    
        @Autowired
        private ResourceLoader resourceLoader;
    
        @Autowired
        private ApplicationEventPublisher applicationEventPublisher;
    
        @Autowired
        private ApplicationContext applicationContext;
    
        @PostConstruct
        public void init() {
            System.out.println("beanFactory == applicationContext :" + (beanFactory == applicationContext));
            System.out.println("beanFactory == applicationContext.getAutowireCapableBeanFactory() :" + (beanFactory == applicationContext.getAutowireCapableBeanFactory()));
            System.out.println("resourceLoader == applicationContext :" + (resourceLoader == applicationContext));
            System.out.println("applicationEventPublisher == applicationContext :" + (applicationEventPublisher == applicationContext));
        }
    
        @PostConstruct
        public void initByLookUp() {
            getBean(BeanFactory.class);
            getBean(ResourceLoader.class);
            getBean(ApplicationEventPublisher.class);
            getBean(ApplicationContext.class);
        }
    
        private <T> T getBean(Class<T> beanType) {
            try {
                return beanFactory.getBean(beanType);
            } catch (NoSuchBeanDefinitionException e) {
                System.err.println("当前类型:" + beanType.getName() + "无法在 BeanFactory 中查找!");
            }
            return null;
        }
    
        public static void main(String[] args) {
            // 创建BeanFactory的容器
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
            // 注册Configuration Class 配置类 -> Spring Bean
            applicationContext.register(DependencySourceDemo.class);
    
            // 启动应用上下文
            applicationContext.refresh();
    
            // 依赖查找 DependencySourceDemo Bean
            DependencySourceDemo demo = applicationContext.getBean(DependencySourceDemo.class);
    
    
            // 显示的关闭spring应用上下文
            applicationContext.close();
        }
    }
    
    
    • 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
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73

    运行的结果如下:

    在这里插入图片描述

    这儿的对象我们称之为spring的非托管对象,那么是怎么注册的。具体的如下:

    在这里插入图片描述

    4.Spring容器管理和游离对象

    依赖对象

    在这里插入图片描述

    5.Spring BeanDefinition 作为依赖来源

    要素

    • 元数据: BeanDefinition
    • 注册: BeanDefinitionRegistry#registerBeanDefinition
    • 类型: 延迟和非延迟
    • 顺序: Bean 生命周期顺序按照注册顺序

    6.单例对象作为依赖来源

    要素

    • 来源: 外部普通 Java 对象( 不一定是 POJO)
    • 注册: SingletonBeanRegistry#registerSingleton

    限制

    • 无生命周期管理
    • 无法实现延迟初始化 Bean

    7.非 Spring 容器管理对象作为依赖来源

    要素

    • 注册: ConfigurableListableBeanFactory#registerResolvableDependency

    限制

    • 无生命周期管理
    • 无法实现延迟初始化 Bean
    • 无法通过依赖查找

    具体的代码如下:

    package org.learn.spring.dependency.source;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    
    import javax.annotation.PostConstruct;
    
    // ResolvableDependency 作为依赖来源
    // 这儿的依赖的注入只能是类型的依赖的注入
    public class ResolvableDependencySourceDemo {
    
        @Autowired
        private String value;
    
        @PostConstruct
        public void init(){
            System.out.println(value);
        }
    
        public static void main(String[] args) {
            // 创建BeanFactory的容器
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
            // 注册Configuration Class 配置类 -> Spring Bean
            applicationContext.register(ResolvableDependencySourceDemo.class);
    
            applicationContext.addBeanFactoryPostProcessor(beanFactory -> {
                // 注册 Resolvable Dependency
                beanFactory.registerResolvableDependency(String.class, "Hello,World");
            });
    
            // 启动应用上下文
            applicationContext.refresh();
            
    
            // 显示的关闭spring应用上下文
            applicationContext.close();
        }
    }
    
    
    • 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

    8.外部化配置作为依赖来源

    要素

    • 类型: 非常规 Spring 对象依赖来源

    限制

    • 无生命周期管理
    • 无法实现延迟初始化 Bean
    • 无法通过依赖查找

    具体的代码如下

    user.id=1
    usr.name=甘雨
    user.resource=classpath:/META-INF/default.properties
    
    • 1
    • 2
    • 3
    package org.learn.spring.dependency.source;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.PropertySource;
    import org.springframework.core.io.Resource;
    
    import javax.swing.text.StyleConstants;
    
    // 外部化配置作为依赖的来源
    @PropertySource(value = "classpath:/META-INF/default.properties",encoding = "UTF-8")
    @Configuration
    public class ExternalConfigurationDependencySourceDemo {
    
        @Value("${user.id:-1}")
        private Long id;
    
        @Value("${usr.name:}")
        private String name;
    
        @Value("${user.resource:classpath:/META-INF/default.properties}")
        private Resource resource;
    
        public static void main(String[] args) {
            // 创建BeanFactory的容器
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
            // 注册Configuration Class 配置类 -> Spring Bean
            applicationContext.register(ExternalConfigurationDependencySourceDemo.class);
    
            // 启动应用上下文
            applicationContext.refresh();
    
            // 依赖查找 ExternalConfigurationDependencySourceDemo Bean
            ExternalConfigurationDependencySourceDemo demo = applicationContext.getBean(ExternalConfigurationDependencySourceDemo.class);
    
            System.out.println("demo.id = " + demo.id);
            System.out.println("demo.name = " + demo.name);
            System.out.println("demo.resource = " + demo.resource);
    
            // 显示的关闭spring应用上下文
            applicationContext.close();
        }
    }
    
    
    • 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

    9.再来简单的看一下相应的源码

    注册BeanDefinition,具体的代码如下:

    	@Override
    	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
    			throws BeanDefinitionStoreException {
    
    		Assert.hasText(beanName, "Bean name must not be empty");
    		Assert.notNull(beanDefinition, "BeanDefinition must not be null");
    
        // 我们这儿所有的BeanDefinition的类型都是AbstractBeanDefinition AbstractBeanDefinition是所有的BeanDefinition的超类
    		if (beanDefinition instanceof AbstractBeanDefinition) {
    			try {
            // 这儿会校验BeanDefinition,这儿我不会做过多的赘述,后面有专门的博客来做介绍
    				((AbstractBeanDefinition) beanDefinition).validate();
    			}
    			catch (BeanDefinitionValidationException ex) {
    				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
    						"Validation of bean definition failed", ex);
    			}
    		}
    
        // 先查找对应的BeanDefinition是否存在
    		BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
    		if (existingDefinition != null) {
          // 如果存在的话,看看这个BeanDefinition是否可以被覆盖,如果可以被覆盖,就重新存入Map中去,springFramework默认是true,是可以被覆盖,在springboot这个值被被改成了false,这儿就会抛出异常。
    			if (!isAllowBeanDefinitionOverriding()) {
    				throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
    			}
    			else if (existingDefinition.getRole() < beanDefinition.getRole()) {
    				// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
    				if (logger.isInfoEnabled()) {
    					logger.info("Overriding user-defined bean definition for bean '" + beanName +
    							"' with a framework-generated bean definition: replacing [" +
    							existingDefinition + "] with [" + beanDefinition + "]");
    				}
    			}
    			else if (!beanDefinition.equals(existingDefinition)) {
    				if (logger.isDebugEnabled()) {
    					logger.debug("Overriding bean definition for bean '" + beanName +
    							"' with a different definition: replacing [" + existingDefinition +
    							"] with [" + beanDefinition + "]");
    				}
    			}
    			else {
    				if (logger.isTraceEnabled()) {
    					logger.trace("Overriding bean definition for bean '" + beanName +
    							"' with an equivalent definition: replacing [" + existingDefinition +
    							"] with [" + beanDefinition + "]");
    				}
    			}
    			this.beanDefinitionMap.put(beanName, beanDefinition);
    		}
    		else {
          // 判断当前的BeanDefinition是否在创建中
    			if (hasBeanCreationStarted()) {
    				// Cannot modify startup-time collection elements anymore (for stable iteration)
    				synchronized (this.beanDefinitionMap) {
              // 将对应的key为BeanName value的值为BeanDefinition存放到beanDefinitionMap 中去
    					this.beanDefinitionMap.put(beanName, beanDefinition);
    					List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
    					updatedDefinitions.addAll(this.beanDefinitionNames);
    					updatedDefinitions.add(beanName);
              // 将对应的BeanName的Map进行更新
    					this.beanDefinitionNames = updatedDefinitions;
    					removeManualSingletonName(beanName);
    				}
    			}
    			else {
    				// Still in startup registration phase
            // 如果没有创建就将key为BeanName value的值为BeanDefinition存放到beanDefinitionMap 中去
    				this.beanDefinitionMap.put(beanName, beanDefinition);
            // 将对应的BeanName存到beanDefinitionNames的List中去
    				this.beanDefinitionNames.add(beanName);
    				removeManualSingletonName(beanName);
    			}
    			this.frozenBeanDefinitionNames = null;
    		}
    
    		if (existingDefinition != null || containsSingleton(beanName)) {
    			resetBeanDefinition(beanName);
    		}
    	}
    
    • 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
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80

    从上面的的代码我们可以知道BeanDefinition是存在beanDefinitionMap的Map中去,key 是beanName,valueBeanDefinition。同时将beanName存到beanDefinitionNames的List中去。

    注册单例对象,具体的代码如下:

    	@Override
    	public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
        // 走来调用的是父类的方法
    		super.registerSingleton(beanName, singletonObject);
    		updateManualSingletonNames(set -> set.add(beanName), set -> !this.beanDefinitionMap.containsKey(beanName));
    		clearByTypeCache();
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    可以看到我们走来调用的是父类的方法org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#registerSingleton

    具体的代码如下:

    	@Override
    	public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
    		Assert.notNull(beanName, "Bean name must not be null");
    		Assert.notNull(singletonObject, "Singleton object must not be null");
    		synchronized (this.singletonObjects) {
          // 先获取对应的单例对象,如果存在直接抛出异常
    			Object oldObject = this.singletonObjects.get(beanName);
    			if (oldObject != null) {
    				throw new IllegalStateException("Could not register object [" + singletonObject +
    						"] under bean name '" + beanName + "': there is already object [" + oldObject + "] bound");
    			}
    			addSingleton(beanName, singletonObject);
    		}
    	}
    	protected void addSingleton(String beanName, Object singletonObject) {
    		synchronized (this.singletonObjects) {
          // 将这个单例的对象存到对应Map中去,key为beanName value为singletonObject
    			this.singletonObjects.put(beanName, singletonObject);
          // 从singletonFactories中移出beanName
    			this.singletonFactories.remove(beanName);
          // 从earlySingletonObjects中移出beanName
    			this.earlySingletonObjects.remove(beanName);
          // 从registeredSingletons中添加beanName
    			this.registeredSingletons.add(beanName);
    		}
    	}
    
    • 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

    从上面的代码我们可以知道单例的对象是添加singletonObjectsMap中keybeanNamevalue是这个单例的对象。同时beanName也会存到registeredSingletons中去。

    ResolvableDependency最后是不受spring管理的对象,注册的过程如下:

    	@Override
    	public void registerResolvableDependency(Class<?> dependencyType, @Nullable Object autowiredValue) {
    		Assert.notNull(dependencyType, "Dependency type must not be null");
    		if (autowiredValue != null) {
          // 是ObjectFactory 直接抛出异常
    			if (!(autowiredValue instanceof ObjectFactory || dependencyType.isInstance(autowiredValue))) {
    				throw new IllegalArgumentException("Value [" + autowiredValue +
    						"] does not implement specified dependency type [" + dependencyType.getName() + "]");
    			}
          // 将对应的对象存到resolvableDependencies Map中去 key为dependencyType value为autowiredValue
    			this.resolvableDependencies.put(dependencyType, autowiredValue);
    		}
    	}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    上面的代码就是将这个对象存到resolvableDependencies存到Map中去,key为dependencyType value为autowiredValue。上面的就是所有的依赖的注入的来源。而依赖的查找只会BeanDefinition的和singletonObjects这两个,这部分源码后面在介绍。

    10.面试题

    10.1 注入和查找的依赖来源是否相同?

    否, 依赖查找的来源仅限于 Spring BeanDefinition 以及单例对象, 而依赖注入的来源还包括 Resolvable Dependency 以及@Value 所标注的外部化配置

    10.2 单例对象能在 IoC 容器启动后注册吗?

    可以的, 单例对象的注册与 BeanDefinition 不同, BeanDefinition会被 ConfigurableListableBeanFactory#freezeConfiguration() 方法影响, 从而冻结注册, 单例对象则没有这个限制。

    10.3 Spring 依赖注入的来源有哪些?

    • Spring BeanDefinition
    • 单例对象
    • Resolvable Dependency
    • @Value 外部化配置
  • 相关阅读:
    智能问答(Question Answering)的主要研究方向
    C++默认参数(实参)
    深入理解requests库和使用方法
    RocketMQ源码阅读(五)MappedFileQueue
    从替代走向引领,永洪科技迈向全球化
    使用gcc编译.s汇编
    STM32与物联网01-ESP8266基本操作
    如何用蓝牙实现无线定位(一)--系统原理
    实现退出登录
    Java类和对象(二)
  • 原文地址:https://blog.csdn.net/qq_36434742/article/details/128037530