zoukankan      html  css  js  c++  java
  • Spring源码之IOC容器创建、BeanDefinition加载和注册和IOC容器依赖注入

    总结

    1. 在SpringApplication#createApplicationContext()执行时创建IOC容器,默认DefaultListableBeanFactory
    2. 在AbstractApplicationContext#refresh()方法内执行invokeBeanFactoryPostProcessors(beanFactory);中完成BeanDefinition的资源定位、加载和注册
    3. singleton的bean在AbstractApplicationContext#finishBeanFactoryInitialization()入口,开始调用getBean进行bean的实例化、属性注入、和初始化等步骤;(非singleton的bean则在第一次getBean时触发)
    4. 以上三步完成IOC容器实现

    IOC容器创建

    beanFactory创建在SpringApplication#createApplicationContext()执行过程

    context = createApplicationContext();
    
    protected ConfigurableApplicationContext createApplicationContext() {
    	return this.applicationContextFactory.create(this.webApplicationType);
    }
    
    private ApplicationContextFactory applicationContextFactory = ApplicationContextFactory.DEFAULT;
    

    调用匿名函数

    ApplicationContextFactory DEFAULT = (webApplicationType) -> {
    	try {
    		switch (webApplicationType) {
    		case SERVLET:
    			return new AnnotationConfigServletWebServerApplicationContext();
            ......
    };
    

    先初始化父类GenericWebApplicationContext

    public GenericWebApplicationContext() {
    	super();
    }
    
    public GenericApplicationContext() {
    	this.beanFactory = new DefaultListableBeanFactory();
    }
    

    BeanDefinition的Resource定位、载入及注册

    BeanDefinition的处理在AbstractApplicationContext#refresh()中invokeBeanFactoryPostProcessors(beanFactory);中完成

    	@Override
    	public void refresh() throws BeansException, IllegalStateException {
    		synchronized (this.startupShutdownMonitor) {
                ......
    			try {
                    ......
    				// Invoke factory processors registered as beans in the context.
    				invokeBeanFactoryPostProcessors(beanFactory);
                    ......
    			}
    
    		}
    	}
    
    BeanDefinition的Resource定位

    调用链:

    AbstractApplicationContext#refresh() --> AbstractApplicationContext#invokeBeanFactoryPostProcessors() --> PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors() --> PostProcessorRegistrationDelegate#invokeBeanDefinitionRegistryPostProcessors() --> ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry()--> ConfigurationClassPostProcessor#processConfigBeanDefinitions() --> ConfigurationClassPostProcessor#parse() --> ConfigurationClassPostProcessor#processConfigurationClass() -->
    ConfigurationClassParser#parse() -->
    ConfigurationClassParser#doProcessConfigurationClass() -->
    ComponentScanAnnotationParser#parse() --> ClassPathBeanDefinitionScanner#doScan() --> ClassPathScanningCandidateComponentProvider#findCandidateComponents() --> ClassPathScanningCandidateComponentProvider#scanCandidateComponents

    在ConfigurationClassParser#doProcessConfigurationClass()中,会将@PropertySource、@ComponentScan、@Import、@ImportResource、@Bean注解的类进行生成BeanDefinition,并加载注册

    protected final SourceClass doProcessConfigurationClass(
    		ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
    		throws IOException {
    
    	if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
    		// Recursively process any member (nested) classes first
    		processMemberClasses(configClass, sourceClass, filter);
    	}
    
    	// Process any @PropertySource annotations
    	for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
    			sourceClass.getMetadata(), PropertySources.class,
    			org.springframework.context.annotation.PropertySource.class)) {
    		if (this.environment instanceof ConfigurableEnvironment) {
    			processPropertySource(propertySource);
    		}
    		else {
    			logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
    					"]. Reason: Environment must implement ConfigurableEnvironment");
    		}
    	}
    
    	// Process any @ComponentScan annotations
    	Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
    			sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
    	if (!componentScans.isEmpty() &&
    			!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
    		for (AnnotationAttributes componentScan : componentScans) {
    			// The config class is annotated with @ComponentScan -> perform the scan immediately
    			Set<BeanDefinitionHolder> scannedBeanDefinitions =
    					this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
    			// Check the set of scanned definitions for any further config classes and parse recursively if needed
    			for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
    				BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
    				if (bdCand == null) {
    					bdCand = holder.getBeanDefinition();
    				}
    				if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
    					parse(bdCand.getBeanClassName(), holder.getBeanName());
    				}
    			}
    		}
    	}
    
    	// Process any @Import annotations
    	processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
    
    	// Process any @ImportResource annotations
    	AnnotationAttributes importResource =
    			AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
    	if (importResource != null) {
    		String[] resources = importResource.getStringArray("locations");
    		Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
    		for (String resource : resources) {
    			String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
    			configClass.addImportedResource(resolvedResource, readerClass);
    		}
    	}
    
    	// Process individual @Bean methods
    	Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
    	for (MethodMetadata methodMetadata : beanMethods) {
    		configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
    	}
    
    	// Process default methods on interfaces
    	processInterfaces(configClass, sourceClass);
    
    	// Process superclass, if any
    	if (sourceClass.getMetadata().hasSuperClass()) {
    		String superclass = sourceClass.getMetadata().getSuperClassName();
    		if (superclass != null && !superclass.startsWith("java") &&
    				!this.knownSuperclasses.containsKey(superclass)) {
    			this.knownSuperclasses.put(superclass, configClass);
    			// Superclass found, return its annotation metadata and recurse
    			return sourceClass.getSuperClass();
    		}
    	}
    
    	// No superclass -> processing is complete
    	return null;
    }
    

    例如@ComponentScan注解时,会扫描并过滤出,默认主加载类上一个文件夹下,所有文件中有@Component或实现@Component的;并转为Definition,并设置属性,最后向IOC容器(DefaultListableBeanFactory)中注册。其中重要方法ClassPathBeanDefinitionScanner#doScan():

    /**
     * Perform a scan within the specified base packages,
     * returning the registered bean definitions.
     * <p>This method does <i>not</i> register an annotation config processor
     * but rather leaves this up to the caller.
     * @param basePackages the packages to check for annotated classes
     * @return set of beans registered if any for tooling registration purposes (never {@code null})
     */
    protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
    	Assert.notEmpty(basePackages, "At least one base package must be specified");
    	Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
    	for (String basePackage : basePackages) {
    		Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
    		for (BeanDefinition candidate : candidates) {
    			ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
    			candidate.setScope(scopeMetadata.getScopeName());
    			String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
    			if (candidate instanceof AbstractBeanDefinition) {
    				postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
    			}
    			if (candidate instanceof AnnotatedBeanDefinition) {
    				AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
    			}
    			if (checkCandidate(beanName, candidate)) {
    				BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
    				definitionHolder =
    						AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
    				beanDefinitions.add(definitionHolder);
    				registerBeanDefinition(definitionHolder, this.registry);
    			}
    		}
    	}
    	return beanDefinitions;
    }
    

    @Configuration注解的配置类中@Bean等注解的类,往IOC容器中注册则在

    this.reader.loadBeanDefinitions(configClasses);
    
    /**
     * Read a particular {@link ConfigurationClass}, registering bean definitions
     * for the class itself and all of its {@link Bean} methods.
     */
    private void loadBeanDefinitionsForConfigurationClass(
    		ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
    
    	if (trackedConditionEvaluator.shouldSkip(configClass)) {
    		String beanName = configClass.getBeanName();
    		if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
    			this.registry.removeBeanDefinition(beanName);
    		}
    		this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
    		return;
    	}
    
    	if (configClass.isImported()) {
    		registerBeanDefinitionForImportedConfigurationClass(configClass);
    	}
    	for (BeanMethod beanMethod : configClass.getBeanMethods()) {
    		loadBeanDefinitionsForBeanMethod(beanMethod);
    	}
    
    	loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
    	loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
    }
    

    IOC容器依赖注入

    调用链:

    AbstractApplicationContext#refresh() --> AbstractApplicationContext#finishBeanFactoryInitialization() --> DefaultListableBeanFactory#preInstantiateSingletons() --> AbstractBeanFactory#getBean() --> AbstractBeanFactory#doGetBean() --> AbstractAutowireCapableBeanFactory#createBean()
    --> AbstractAutowireCapableBeanFactory#doCreateBean() --> AbstractAutowireCapableBeanFactory#createBeanInstance() --> AbstractAutowireCapableBeanFactory#instantiateBean()

    singleton的bean在AbstractApplicationContext#finishBeanFactoryInitialization()入口,开始调用getBean进行bean的实例化、属性注入、和初始化等步骤;(非singleton的bean则在第一次getBean时触发)

    protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
    		throws BeanCreationException {
    
    	// Instantiate the bean.
    	BeanWrapper instanceWrapper = null;
    	if (mbd.isSingleton()) {
    		instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    	}
    	if (instanceWrapper == null) {
    	    //实例化对象
    		instanceWrapper = createBeanInstance(beanName, mbd, args);
    	}
    	Object bean = instanceWrapper.getWrappedInstance();
    	Class<?> beanType = instanceWrapper.getWrappedClass();
    	if (beanType != NullBean.class) {
    		mbd.resolvedTargetType = beanType;
    	}
    
    	// Allow post-processors to modify the merged bean definition.
    	synchronized (mbd.postProcessingLock) {
    		if (!mbd.postProcessed) {
    			try {
    				applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
    			}
    			catch (Throwable ex) {
    				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    						"Post-processing of merged bean definition failed", ex);
    			}
    			mbd.postProcessed = true;
    		}
    	}
    
    	// Eagerly cache singletons to be able to resolve circular references
    	// even when triggered by lifecycle interfaces like BeanFactoryAware.
    	boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
    			isSingletonCurrentlyInCreation(beanName));
    	if (earlySingletonExposure) {
    		if (logger.isTraceEnabled()) {
    			logger.trace("Eagerly caching bean '" + beanName +
    					"' to allow for resolving potential circular references");
    		}
    		addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    	}
    
    	// Initialize the bean instance.
    	Object exposedObject = bean;
    	try {
    	    //属性注入
    		populateBean(beanName, mbd, instanceWrapper);
    		//初始化对象
    		exposedObject = initializeBean(beanName, exposedObject, mbd);
    	}
    	catch (Throwable ex) {
    		if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
    			throw (BeanCreationException) ex;
    		}
    		else {
    			throw new BeanCreationException(
    					mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
    		}
    	}
    
    	......
    
    	return exposedObject;
    }
    
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出。
  • 相关阅读:
    虚方法表与动态分派机制
    方法重载与invokevirtual字节码指令的关系
    栈桢与操作数栈以及符号引用与直接引用的转换
    通过字节码分析this关键字以及异常表的作用
    JVM synchronized关键字所生成的字节码
    window Chrome 下允许跨域访问服务端接口设置
    JVM Java字节码方法表与属性
    JVM 字节码的结构
    Jar hell问题以及解放方法
    JVM 线程上下文类加载器
  • 原文地址:https://www.cnblogs.com/caozibiao/p/13985651.html
Copyright © 2011-2022 走看看