什么是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
spring bean是单例还是多例,是不是线程安全的
spring的bean默认是单例的,但是spring并没有对bean的线程进行维护所以说是线程不安全的,spring设置单例主要就是为了节约资源。
bean默认单例,所以在一般的请求中没有对成员变量的操作就不会出现问题,多线程下每一个线程都会开辟一个空间对信息进行存储,互不影响;线程不安全是存在成员变量,多线程下资源共享造成的。
解决办法:
-
不使用成员变量
-
加上该注解@Scope("prototype") 使用多例,每次请求都会创建新的
-
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代理。
https://blog.csdn.net/u011277123/article/details/89206722
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属性执行。