spring - Go语言中文社区

spring


什么是spring框架

spring是轻量级的开发框架,主要是为了提高开发效率和系统的可维护性。

什么是bean 是什么是类

类是java虚拟机预先编译成class文件存放到方法区,new的时候会在堆中开辟一个空间存放

 

IOC

ioc就是控制反转,这是一种设计思想,就是将原本程序创建对象的过程交给spring来处理,降低项目的耦合度。

IOC将初始化的对象交给工厂进行创建,工厂通过反射的方式进行创建对象

反射:

先获取对象信息(Class.forName(),对象.getClass(),类名.class)

获取任意的对象和方法等Constructor ctor=  clazz,getConstructor()

实例化对象:Obkect obj = ctor.newInstance()

spring ioc的注入方式

构造器、setter方法、注解

ioc初始化过程

ioc初始化是先读取xml的resource,解析成beanDefinition到map中,调用gertbean的时候时候直接从beanDefinition中取出进行实例化,如果有依赖关系的话就递归调用getBean方法完成依赖

 

 

bean的创建是由new AnnotationConfigApplicationContext(MainConfig4.class) 完成的,里面有一个refresh方法进行创建。

创建AnnotationConfigApplicationContext对象首先会进入有参构造方法,首先AnnotationConfigApplication继承GenericApplicationContext,GenericApplicationContext方法初始化了DefaultListableBeanFactory。

public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
    private final DefaultListableBeanFactory beanFactory;
    private boolean customClassLoader;
    private final AtomicBoolean refreshed;
    public GenericApplicationContext() {
        this.customClassLoader = false;
        this.refreshed = new AtomicBoolean();
        this.beanFactory = new DefaultListableBeanFactory();
    }
}

AnnotationConfigApplicationContext构造方法

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
      
     this();
      
     register(annotatedClasses);
       
     refresh();
}

第一个方法:this

this会调用无参构造方法

public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {

    private final AnnotatedBeanDefinitionReader reader;

    private final ClassPathBeanDefinitionScanner scanner;

    /**
     * Create a new AnnotationConfigApplicationContext that needs to be populated
     * through {@link #register} calls and then manually {@linkplain #refresh refreshed}.
     */
    public AnnotationConfigApplicationContext() {

        this.reader = new AnnotatedBeanDefinitionReader(this);

   
        this.scanner = new ClassPathBeanDefinitionScanner(this);
    }
}

对AnnotationBeanDefinitionReader和AnnotationBeanDefinitionScanner进行了初始化

AnnotationBeanDefinitionReader初始化:

    public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
        this(registry, getOrCreateEnvironment(registry));
    }

参数BeanDefinitionReader这个参数就是AnnotationConfigApplicationContext实例,方法中又直接调用构造方法

    public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        Assert.notNull(environment, "Environment must not be null");
        this.registry = registry;
        this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
        AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
    }

最后一行进入registerAnnotationConfigProcessors()方法

    public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
        registerAnnotationConfigProcessors(registry, null);
    }

registerAnnotationConfigProcessors方法主要代码:

if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}

主要是从ConfigurationClassPostProcessor中获取BeanDefinition

然后执行registerPostProcessor注册bean

private static BeanDefinitionHolder registerPostProcessor(BeanDefinitionRegistry registry,RootBeanDefinition definition, String beanName) {

     definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
     registry.registerBeanDefinition(beanName, definition);
     return new BeanDefinitionHolder(definition, beanName);
}

这个方法设置了一个ROLE 表示是Spring内部的 不是用户自定义的,然后调用registerBeanDefinition

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
            throws BeanDefinitionStoreException {
        this.beanFactory.registerBeanDefinition(beanName, beanDefinition);
    }

在进入registerBeanDefinition主要是以下操作


this.beanDefinitionMap.put(beanName, beanDefinition);


this.beanDefinitionNames.add(beanName);

DefaultListableBeanFactory中存放beanDefiitionMap和beanDefinitionNames。

beanDefinitionMap是Map<String, BeanDefinition>,beanDefinitionNames就是一个List<String>,这里就是把beanName放到List中去

beanDefinitionMap中存放是:key是beanName,value是beanDefinition;beanDefinitionNames是一个集合,存放beanName

this这个方法就是初始化DefaultListableBeanFactory(通过继承GenericApplicationContext实现),然后初始化BeanDefinition,并将BeanDifition信息存放到BeanFactory中。

第二个方法register

register参数是一个数组,是传入的数组,最终会解析为传入的bean

    <T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
            @Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
        //AnnotatedGenericBeanDefinition可以理解为一种数据结构,是用来描述Bean的,这里的作用就是把传入的标记了注解的类
        //转为AnnotatedGenericBeanDefinition数据结构,里面有一个getMetadata方法,可以拿到类上的注解
        AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);

        //判断是否需要跳过注解,spring中有一个@Condition注解,当不满足条件,这个bean就不会被解析
        if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
            return;
        }

        abd.setInstanceSupplier(instanceSupplier);

        //解析bean的作用域,如果没有设置的话,默认为单例
        ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
        abd.setScope(scopeMetadata.getScopeName());

        //获得beanName
        String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

        //解析通用注解,填充到AnnotatedGenericBeanDefinition,解析的注解为Lazy,Primary,DependsOn,Role,Description
        AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);

        //限定符处理,不是特指@Qualifier注解,也有可能是Primary,或者是Lazy,或者是其他(理论上是任何注解,这里没有判断注解的有效性),如果我们在外面,以类似这种
        //AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(Appconfig.class);常规方式去初始化spring,
        //qualifiers永远都是空的,包括上面的name和instanceSupplier都是同样的道理
        //但是spring提供了其他方式去注册bean,就可能会传入了
        if (qualifiers != null) {
            //可以传入qualifier数组,所以需要循环处理
            for (Class<? extends Annotation> qualifier : qualifiers) {
                //Primary注解优先
                if (Primary.class == qualifier) {
                    abd.setPrimary(true);
                }
                //Lazy注解
                else if (Lazy.class == qualifier) {
                    abd.setLazyInit(true);
                }
                //其他,AnnotatedGenericBeanDefinition有个Map<String,AutowireCandidateQualifier>属性,直接push进去
                else {
                    abd.addQualifier(new AutowireCandidateQualifier(qualifier));
                }
            }
        }

        for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
            customizer.customize(abd);
        }

        //这个方法用处不大,就是把AnnotatedGenericBeanDefinition数据结构和beanName封装到一个对象中
        BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);

        definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);

        //注册,最终会调用DefaultListableBeanFactory中的registerBeanDefinition方法去注册,
        //DefaultListableBeanFactory维护着一系列信息,比如beanDefinitionNames,beanDefinitionMap
        //beanDefinitionNames是一个List<String>,用来保存beanName
        //beanDefinitionMap是一个Map,用来保存beanName和beanDefinition
        BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
    }

AnnotationBeanDefinitionBean是通过注解的方式获取的bean,regist是将注解bean的信息注册到容器中。

以上的this和register方法只是实例化了一个工厂,然后注册一些spring内置的bean和我们传入的bean,这个时候spring还没有进行扫描

第三个方法 refresh

1、prepareRefresh();

准备工作,记录下时间,设置已启动状态,检查环境变量等,检查环境标量为核心方法,简单来说就是如果存在环境变量的value为空的话就会抛出异常。停止启动Spring。

2、obtainFreshBeanFactory();

调用AbstractRefreshableApplicationContext.java中的方法。

调用redreshBeanFactory,createBeanFactory创建DefaultListableBeanFactory工厂,loadBeanDefinition初始化 annotationBeanDefinitionReader并且把bean信息解析出来成BeanDefinition注册到DefaultListableBeanFactory中;

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		//核心
		refreshBeanFactory();
		//返回刚刚创建的 BeanFactory
		return getBeanFactory();
}

refreshBeanFactory();

	protected final void refreshBeanFactory() throws BeansException {
		// 判断是否有BeanFactory,如果已经有容器,则销毁容器中的Bean,关闭容器
		if (hasBeanFactory()) {
			destroyBeans();
			closeBeanFactory();
		}
		try {
			//创建DefaultListableBeanFactory,IOC容器
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			//设置序列化id
			beanFactory.setSerializationId(getId());
			//定制beanfactory,设置相关属性,如设置启动参数、开启注解的自动装配等
			customizeBeanFactory(beanFactory);
			//调用载入Bean定义的方法,此类只是定义了抽象方法,通过子类容器实现
			loadBeanDefinitions(beanFactory);
			synchronized (this.beanFactoryMonitor) {
				this.beanFactory = beanFactory;
			}
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}
	}

首先判断是否是有bean工厂,有工厂的话就销毁容器中的bean,然后关闭;

然后创建容器,加载配置信息调用loadBeanDefinition

loadBeanDefinition

这个方法会根据配置信息加载各个bean,然后存放到DefaultListableBeanFactory的BeanDefinitionMap中(BeanDefinitionMap中存放的key是beanName,value是BeanDefinition)

 

初始化BeanDefinitionReader,通过BeanDefinition获取Resource,也就是xml配置文件的位置,并把文件准换成Document对象。然后将Document对象转化成BeanDefition,就是将bean定义的list、map、set等元素进行解析,转换成managed类放在BeanDefinition中,把解析的结果放在BeanDefition对象中并设置到Map中。

参考 : Spring IOC启动流程源码分析一

3、prepareBeanFactory(beanFactory);

对beanFactory的属性值进行一些赋值操作和注册操作。

4、postProcessBeanFactory(beanFactory);

beanFactory准备工作完成之后进行的后置处理工作,beanFactory的后置处理器,空方法;做扩展实现

5、invokeBeanFactoryPostProcessors(beanFactory);

执行BeanFactory的后置处理器,在BeanFactory标准初始化之后执行,调用所有注册的BeanFactoryPostProcessor的Bean。

上面五个步骤已经准备好Bean工厂,注册好所有的Bean定义的信息(Bean还没有创建)

6、registerBeanPostProcessors(beanFactory);

BeanFactory注册Post事件处理器,BeanPostProcessor是Bean的后置处理器,用于监听容器触发的事件,有两个方法:postProcessorBeforInitiailzation和postProcessorAfterInitailzation,分别会在bean初始化之前和初始化之后执行(AOP功能主要在这一步

7、initMessageSource();

初始化MessageSource组件(做国际化功能;消息绑定,消息解析);

8、initApplicationEventMulticaster();

初始化应用事件的广播器

9、onRefresh();

空方法,留给子类处理一些其他的bean

10、registerListeners();

注册监听器

11、finishBeanFactoryInitialization(beanFactory);

实例化所有不是懒加载的单例bean;

1、调用方法:preInstanceSingletons方法;方法中在beanDefinitionNames中获取所有的beanName并且循环遍历,获取bean的信息RootBeanDefinition,验证bean是否是单例,非抽象,是否是懒加载。

2、调用preInstanceSingleton中getBean方法,getBean调用doGetBean方法;

3、doGetBean调用getSingleton的lamada表达式:一个是getSingleton方法,一个是createBean

4、getSingleton方法调用beforeSingletonCreatetion,加入创建中的bean;

5、createBean,调用resolveBeforeInstantiation方法,让BeanPostProcessor先拦截返回代理对象触发postProcessorBeforeInstantiation

6、调用doCreateBean,调用createBeanInstance 创建bean的实例;然后调动populateBean注入属性。调用InitializaBean初始化Bean:执行aware接口,执行后置处理器之前操作beanPostProcessorBeforeInitialization,执行初始化invokeInitMethods,执行后置处理器beanPostProcessorAfterInitialization

7、销毁bean

调用preInstantiateSingletons方法中的getBean();

		//对配置了lazy-init属性的单例模式的Bean进行预实例化处理
		beanFactory.preInstantiateSingletons();

调用preInstantiateSingletons方法 :验证bean(单例、非抽象、懒加载:在使用的时候才会实例化)

public void preInstantiateSingletons() throws BeansException {
		if (logger.isTraceEnabled()) {
			logger.trace("Pre-instantiating singletons in " + this);
		}
		//获取容器中的所有bean,依次进行初始化和创建对象
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

		for (String beanName : beanNames) {
			//获取bean的定义信息
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			//bean不是抽象的、是单实例的、是懒加载的
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
				//判断是否是FactoryBean,是否是实现FactoryBean接口的bean
				if (isFactoryBean(beanName)) {
					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
					if (bean instanceof FactoryBean) {
						final FactoryBean<?> factory = (FactoryBean<?>) bean;
						boolean isEagerInit;
						if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
							isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
											((SmartFactoryBean<?>) factory)::isEagerInit,
									getAccessControlContext());
						}
						else {
							isEagerInit = (factory instanceof SmartFactoryBean &&
									((SmartFactoryBean<?>) factory).isEagerInit());
						}
						if (isEagerInit) {
							getBean(beanName);
						}
					}
				}
				else {
					//不是工厂Bean,利用getBean创建对象
					getBean(beanName);
				}
			}
		}

	}

getBean最终调用的是doGetBean方法:

1、是否是在原型的创建的bean中

           if (this.isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }

进入一个lamda表达式

				if (mbd.isSingleton()) {
					//调用匿名内部类创建Bean实例对象
					sharedInstance = getSingleton(beanName, () -> {
						try {
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							// Explicitly remove instance from singleton cache: It might have been put there
							// eagerly by the creation process, to allow for circular reference resolution.
							// Also remove any beans that received a temporary reference to the bean.
							//从单例模式的Bean缓存中清除实例对象
							destroySingleton(beanName);
							throw ex;
						}
					});
					//获取给定Bean的实力对象
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}

getSingleton方法

    public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(beanName, "Bean name must not be null");
        synchronized(this.singletonObjects) {
            //先获取缓存的bean
            Object singletonObject = this.singletonObjects.get(beanName);
               //没有缓存的bean
            if (singletonObject == null) {
                if (this.singletonsCurrentlyInDestruction) {
                    throw new BeanCreationNotAllowedException(beanName, "Singleton bean creation not allowed while singletons of this factory are in destruction (Do not request a bean from a BeanFactory in a destroy method implementation!)");
                }

                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
                }
                //---标记当前bean被创建过
                this.beforeSingletonCreation(beanName);
                boolean newSingleton = false;
                boolean recordSuppressedExceptions = this.suppressedExceptions == null;
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = new LinkedHashSet();
                }

                try {
                    //传入的lamada表达式 里面有createBean方法
                    singletonObject = singletonFactory.getObject();
                    newSingleton = true;
                } catch (IllegalStateException var16) {
                    singletonObject = this.singletonObjects.get(beanName);
                    if (singletonObject == null) {
                        throw var16;
                    }
                } catch (BeanCreationException var17) {
                    BeanCreationException ex = var17;
                    if (recordSuppressedExceptions) {
                        Iterator var8 = this.suppressedExceptions.iterator();

                        while(var8.hasNext()) {
                            Exception suppressedException = (Exception)var8.next();
                            ex.addRelatedCause(suppressedException);
                        }
                    }

                    throw ex;
                } finally {
                    if (recordSuppressedExceptions) {
                        this.suppressedExceptions = null;
                    }

                    this.afterSingletonCreation(beanName);
                }

                if (newSingleton) {
                    this.addSingleton(beanName, singletonObject);
                }
            }

            return singletonObject;
        }
    }

 1、this.beforeSingletonCreation(beanName); singletonsCurrentlyInCreation,这是一个set集合,正在创建的单例bean集合,add之后就是正在创建的bean

  protected void beforeSingletonCreation(String beanName) {
        if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }
    }
2、singletonObject = singletonFactory.getObject();  传入的lamada表达式,之后就是进入lamada表达式,进入createBean方法

同样createBean最终调用doCreateBean方法

	 
	/**
	 * 真正创建Bean的方法
	 */
	protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
			throws BeanCreationException {

 
		//封装被创建的Bean对象
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			//根据指定bean使用对应的策略创建新的实例,如:工厂方法、构造函数自动注入,简单初始化
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		final Object bean = instanceWrapper.getWrappedInstance();
		//获取实例化对象的类型
		Class<?> beanType = instanceWrapper.getWrappedClass();
		if (beanType != NullBean.class) {
			mbd.resolvedTargetType = beanType;
		}

 
		//调用PostProcessor后置处理器
		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;
			}
		}

 
		// 向容器中缓存单例模式的Bean对象,以防止循环引用
		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));
		}

 
		//Bean对象的初始化,依赖注入在此触发,这个对象在初始化完成之后返回依赖注入完成后的Bean
		Object exposedObject = bean;
		try {
			//将Bean实例对象封装,并且将Bean定义中配置的属性值赋给实例对象
			populateBean(beanName, mbd, instanceWrapper);
			//初始化Bean对象,Bean实例对象的依赖注入完成之后,为Bean实例对象应用BeanPostProcessor后置处理器
			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);
			}
		}

		if (earlySingletonExposure) {
			//获取指定名称的已注册的单例模式的Bean对象
			Object earlySingletonReference = getSingleton(beanName, false);
			if (earlySingletonReference != null) {
				//根据名称获取已注册的Bean和正在实例化的Bean是同一个
				if (exposedObject == bean) {
					//当前实例化的Bean初始化完成
					exposedObject = earlySingletonReference;
				}
				//当前Bean依赖其他Bean,并且当发生循环引用时不允许创建新的实例对象
				else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
					String[] dependentBeans = getDependentBeans(beanName);
					Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
					//获取当前Bean所依赖的其他Bean
					for (String dependentBean : dependentBeans) {
						//对依赖Bean进行类型检查
						if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
							actualDependentBeans.add(dependentBean);
						}
					}
					if (!actualDependentBeans.isEmpty()) {
						throw new BeanCurrentlyInCreationException(beanName,
								"Bean with name '" + beanName + "' has been injected into other beans [" +
								StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
								"] in its raw version as part of a circular reference, but has eventually been " +
								"wrapped. This means that said other beans do not use the final version of the " +
								"bean. This is often the result of over-eager type matching - consider using " +
								"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
					}
				}
			}
		}

		// Register bean as disposable.
		// 注册完成依赖注入的Bean
		try {
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
		}

		return exposedObject;
	}

创建Bean的实例

instanceWrapper = createBeanInstance(beanName, mbd, args);//创建bean的实例。核心

调用

instantiate(mbd, beanName, this)

调用 

instantiateBean(beanName, mbd);
instantiateClass(Constructor<T> ctor, Object... args)
ctor.newInstance(args)

经过反推构造方法,然后调用ctor.newInstance(args) 反射创建bean

现在的bean不是仅仅是一个对象

判断当前这个bean是不是一个单例的bean ,支不支持循环依赖,然后加入一级缓存

    protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(singletonFactory, "Singleton factory must not be null");
        synchronized(this.singletonObjects) {
            if (!this.singletonObjects.containsKey(beanName)) {
                this.singletonFactories.put(beanName, singletonFactory);
                this.earlySingletonObjects.remove(beanName);
                this.registeredSingletons.add(beanName);
            }

        }
    }

填充bean的属性

populateBean(beanName, mbd, instanceWrapper);//填充属性,炒鸡重要

执行

 

 

1、检查是否存在缓存中,不存在创建bean

Object sharedInstance = getSingleton(beanName);

2、检查是否在beanDefition中是否存在beanName命名的beanDefition

3、没有在beanDefition中获取到bean,那么创建beanDefition

final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);

4、创建bean的实例 createBean

由AbstractAutowireCapableBeanFactory方法实现bean的创建。

在createBean方法中调用doCreateBean,doCreateBean 调用populateBean开始依赖注入

一个是创建Bean的实例(createBeanInstance),一个是进行依赖注入(populateBean)

4.1、createBeanInstance通过反射创建bean,还有就是cglib动态代理创建bean

4.2、populateBean进行依赖注入

 

12、finishRefresh();

 

参考 :ioc创建bean的流程  、 Spring IOC容器启动流程

 

 

 

定义bean的信息,可以是xml也可以是注解的方式,通过beanDefinitionReader读定义的bean的信息,最终这些bean的信息都是读取到beanDefinition中。

beanFactory通过反射实例化对象

初始化对象

init-method

完整对象

通过getBean方法调用对象

对象的创建是实例化然后初始化。实例化是在堆中申请内存空间,属性都是默认的,初始化是对对象的属性进行赋值或者初始化方法进行调用。

beandefinitionReader

beanFactoryPostProcessor

实现<property name= 'url' value = '${url}'>中 ${}这个值的替换

beanFactory

beanPostProcessor

实现AOP的动态代理(AOP代理是jdk或者 cglib),对象实例化之后初始化之前是before 实例化之后和完成对象创建之前是after

spring观察者模式:在spring容器中,有一系列的监听器,用来完成不同阶段做不同的工作。

bean实现的Aware接口是什么?

Aware是值的是后缀是aware的一些接口。

实现aware最重要的目的就是为了在程序运行过程中,通过某些bean对象直接获取当前对象的上下文的某些值。

 

Spring Bean 生命周期

spring循环依赖

什么是循环依赖

 

怎么解决循环依赖

循环依赖问题出现在设置对象属性的时候,设置对象属性主要是构造器和set方法,构造器是无法解决的。所以使用set方法

spring 的bean对象默认是单例的,spring 通过提前暴露对象的方法解决循环依赖;

解决循环依赖先要了解bean的生命周期。

创建对象是通过实例化和初始化完成的,实例化是在堆空间中开辟一块控件,对象的属性值都是一些默认值;初始化来设置属性,调用初始化方法。

bean在实例化之后完成初始化的操作;

1、填充属性,populateBean();

2、执行aware接口

3、执行beanProcessor的before 方法

4、init方法

5、执行BeanProcessor的after方法

6、完整对象

7、销毁对象

创建对象的时候,先是进行实例化,然后进行初始化,那么先将预先初始化的对象存储到Map中,等后续需要的时候再根据对象的引用完成赋值操作。

三级缓存

1、Map<String ,Object>singletonObjects = new ConcurrentHashMap(256) 存放成品对象

2、Map<String ,Object> earlySingletonObjects = new HashMap(16) 存放半成品对象

3、Map<String ,ObjectFactory/<?>> singletionFactories = new ConcurrentHashMap(16) lambda表达式

 

1、首先初始化bean A,执行getBean(A),执行getBean中doGetBean(A)方法。

2、执行getSingletion方法从缓存中获取bean A,

3、没有获取到一级缓存(singletionObjects.get(A))中的bean A并且A对象没有在创建中,进行bean A 创建,分别执行createBean和doCreateBean,初始化bean:createBeanInstance,对bean进行实例化操作,可以在堆里面开辟一块空间 。

4、然后将初始化的bean但是还没有赋值属性的bean存入三级缓存中,执行addSingletonFactory,此时存放的是A的lamada。

5、执行applyPropertyValue对bean的属性进行填充。属性填充触发对依赖bean B的初始化,依赖bean B初始化的时候同样走1,2,3,4,5

6、此时B需要在容器中获取A对象,还是走1、2,A对象没有在一级缓存(singletionObjects.get(A))中但是A对象在创建中,从一级缓存中取值,没有取到那么在二级缓存(earlySingletionObjectsget(A))中取值,没有取到值,那么从三级缓存(singletionFactorys.get(A))中取值,取出之后不是A对象,而是A的lamada表达式,他是一个半成品,把A存储到二级缓存中,删除三级缓存(singletionObjects.remove())。

7、设置B的属性,此时B是一个完整状态,因为B中设置的A的属性已经设置完了,执行addSingletion:存储B到一级缓存(singletionObject.put),删除三级、二级缓存 

8、然后现在对A进行注入,重复7,A实例化的时候直接从一级缓存中获取B,循环结束。

循环依赖不会解决构造器注入,只有单例的bean依靠三级缓存可以实现,因为多例每次都会创建新的bean,不会缓存

参考:

解决办法是三级缓存

循环依赖解决

 

只使用一级或者二级可不可以

只适用一级的话,那么就意味着成品与半成品都存放在一级缓存中,那么就有可能会获取到对象的非完成状态,此时不能使用,所以需要一级和二级来区分不同状态的对象

只有二级的话可以解决循环依赖,但是在使用AOP的时候或者使用代理对象的时候需要使用三级缓存,三级缓存是为了解决代理过程中的循环依赖的问题。

如果一个对象需要代理的话,在容器中会有两个版本:一个是原始对象,通过反射创建出来的,一个是通过cglib或者是jdk代理创建的

 

 

 

 

BeanFactory和FactoryBean区别

 

spring IOC的作用域

其实就是bean的作用域:

(1)singleton:(单例模式)默认,每个容器中只有一个bean的实例

(2)prototype:(多例模式)为每一个bean请求提供一个实例

一般来说下面几种作用域,在开发的时候一般都不会用,99.99%的时候都是用singleton单例作用域

(3)request:为每一个网络请求创建一个实例,在请求完成以后,bean会失效并被垃圾回收器回收

(4)session:与request范围类似,确保每个session中有一个bean的实例,在session过期后,bean会随之失效

(5)global-session

spring 不指定作用域,默认使用singleleton作用域:因为java 创建实例以及销毁实例都需要系统开销,prototype开销比较大,而singleton一旦创建成功可以重复使用。

在controller 或者是其他一些层里面定义一些全局的变量,会不会引起线程安全的问题,怎么解决?

controller修饰的本身就是单例,而访问的时候有可能是多线程访问,那么就会造成安全性的问题;

不定义成员变量

使用注解@Scope(“prototype”)设置为多例模式

threadLocal

 

 

 

spring自动装配

https://www.cnblogs.com/cxxxxxx/p/13417469.html

https://www.cnblogs.com/merryyou/p/11724750.html

springboot自动装配

 

spring bean是单例还是多例,是不是线程安全的

spring的bean默认是单例的,但是spring并没有对bean的线程进行维护所以说是线程不安全的,spring设置单例主要就是为了节约资源。

bean默认单例,所以在一般的请求中没有对成员变量的操作就不会出现问题,多线程下每一个线程都会开辟一个空间对信息进行存储,互不影响;线程不安全是存在成员变量,多线程下资源共享造成的。

解决办法:

  1. 不使用成员变量

  2. 加上该注解@Scope("prototype") 使用多例,每次请求都会创建新的

  3. localthread

参考:

https://blog.csdn.net/yuyeqianhen/article/details/88965379

https://blog.csdn.net/cheliao3946/article/details/100969937

https://blog.csdn.net/suifeng629/article/details/106310664/

https://blog.csdn.net/weixin_42324471/article/details/90603651

 

Spring线程并发问题

线程并发

AOP

aop是切面编程,本意是降低程序的耦合度,实现是通过代理实现的,基于接口实现的jdk或者是基于继承实现的cglib;

使用jdk还是cglib是spring中做判断,接口的话就是jdk实现,集成的话就是cglib实现。

代理

aspectJ:静态代理,在编译的时候生成Aop代理类,并将aspectJ切面织入到java字节码中,在运行的时候就是增强之后的Aop对象

动态代理:不会去修改java的字节码,每次运行的时候在内存中临时生成一个AOP对象,这个AOP对象包括目标对象的所有方法,在特定的切点做增强处理,并回调原方法。

JDK

要求被代理类实现接口,JDK动态代理的核心就是InvocationHandle和proxy,在获取对象的时候,使用Proxy动态的创建目标类的代理类,当代理类调用真实对象方法时,InvocationHandler方法通过invoke()反射调用目标类中的代码。

CGLib

运行的时候动态的指定类的子类,覆盖期制定方法并增强,CGLib通过继承的方式实现,final类无法实现CGLib代理。

 

AOP 和代理

https://blog.csdn.net/u011277123/article/details/89206722

AOP热门面试

Spring的事务实现原理是什么?能聊聊你对事务传播机制的理解吗?

不考虑事物隔离并发会引起的问题

脏读 : 一个事物读取另一个事物未提交的数据

不可重复读 : 一个事物读取到另一个事物已提交的update的数据导致多次查询结果不一致

事物隔离级别

虚幻读 :一个事物读取到另一个事物已经提交的insert的数据导致多次查询数据不一致

未提交读 : 脏读 、可重复读 、幻读

已提交读 :可重复读 幻读 

可重复读 : 幻读

串行化 :避免所有的问题

Spring事务调用类自己方法失效解决办法和原因

原因是方法没有走代理 spring事物是代理实现的 

解决

  • 把方法放到不同的类中

  • 自己注入自己

  • 使用代理

主要考察1. 事务的实现原理,2. 事务的传播机制

1. 实现原理:加一个@Transactional注解,Spring会使用AOP,对这个方法在执行前,先开启事务,在执行完毕后,根据方法是否报错,来决定是回滚还是提交事务。

2. 传播机制:

1. PROPAGATION_REQUIRED(默认):       如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置。

2. PROPAGATION_SUPPORTS(少用):      支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行。‘

3. PROPAGATION_MANDATORY(很少用):    支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。

4. PROPAGATION_REQUIRES_NEW(常用):   创建新事务,无论当前存不存在事务,都创建新事务。

5. PROPAGATION_NOT_SUPPORTED(很少用):以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

6. PROPAGATION_NEVER(很少用):        以非事务方式执行,如果当前存在事务,则抛出异常。

7. PROPAGATION_NESTED(用):           如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则按REQUIRED属性执行。

 

 

spring基本面试问题

https://blog.csdn.net/a745233700/article/details/80959716

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/weixin_42167717/article/details/106520734
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2021-06-26 22:05:19
  • 阅读 ( 494 )
  • 分类:

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢