Spring源码开始

Spring源码开始

一、名词解释

BeanDefinition接口:Bean的定义信息

一个 BeanDefinition 描述了一个 bean 实例,我们的@Bean,@Component,XML文件中的那些都会解析为他

它具有属性值、构造函数参数值和由具体实现提供的更多信息

实现方式:XML,YAML,注解,properties

属性:

  1. beanclass:表示一个bean的类型,Spring在创建Bean的过程中会根据此属性来实例化得到对象
  2. scope:表示一个bean的作用域,singleton单例,prototype多例
  3. isLazy:表示一个bean是不是需要懒加载,原型bean的isLazy属性不起作用,懒加载的单例bean,会在第一次getBean的时候生成该Bean,非懒加载的单例Bean,则会在Spring启动过程中直接生成好
  4. dependsOn:表示一个bean在创建之前所依赖的其他bean,在一个bean创建之前她所依赖的这些bean得先全部创建好
  5. parimary:表示一个bean是主bean,在Spring中的一个类型可以有多个bean对象,在进行依赖注入时,如果根据类型找到了多个bean,此时会判断这些bean中是否存在一个主bean,如果存在,则将这个bean注入给属性
  6. initMethodName:bean的初始化方法,一个bean的生命周期过程中有一个初始化,Spring会在这个步骤去调用bean的初始化方法,初始化逻辑由程序员自己控制,表示程序员可以自定义逻辑对bean进行加工
        AnnotationConfigApplicationContext t = new AnnotationConfigApplicationContext();
        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition(); //就是一个配置文件中拿信息的过程
        beanDefinition.setBeanClass(UserDaoImpl.class);  //使用beanDefinition定义bean,相当于给bean定义类型
        t.registerBeanDefinition("UserDao",beanDefinition); //将bean注入到容器中

BeanDefinitionReader

bean 定义阅读器的简单界面。

使用资源和字符串位置参数指定加载方法。

BeanFactory

访问 Spring bean 容器的根接口,外部访问容器的大门,通过他里边定义的方法操作容器,各种实现类去实现完善他的功能

		DefaultListableBeanFactory bean = new DefaultListableBeanFactory();
        bean.registerSingleton("UserDao",new UserDaoImpl());
        //先永beanfactory对象中的方法定义beanname,创建一个对象
        UserDaoImpl userDao = bean.getBean("UserDao", UserDaoImpl.class);
        //然后再getBean获取这个对象
        System.out.println(userDao);
        //beanfactory就是一个这样的功能

beandefinition拿出配置文件中的“原材料”,然后beanfactory进行生产出来的产品就是bean

AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder
    .genericBeanDefinition().getBeanDefinition(); 
DefaultListableBeanFactory bean = new DefaultListableBeanFactory();       beanDefinition.setBeanClass(UserDaoImpl.class);        
//使用beanDefinition定义类型,单例多例,懒加载等等        
bean.registerBeanDefinition("User",beanDefinition);        
//beanfactory注册,容器自动生成对象        
UserDaoImpl userDao = bean.getBean("User", UserDaoImpl.class);        
//然后再getBean获取这个对象        
System.out.println(userDao);        
//他们之间就是这么一个联系

BeanFactoryPostProcessor

例:可以替换xml中占位符的内容通过配置文件中定义好的对应值

允许自定义修改applicationContext的 bean 定义,

实现了此接口的类,利用其中的对象拿到BeanDefinition对象,然后就可以修改里边的属性

BeanPostProcessor

是Spring所提供的一种扩展机制,可以利用该机制对Bean进行定制加工

其中方法

  1. postProcessBeforeInitialization:初始化前方法,表示可以利用这个方法来对Bean在初始化之前进行自定义加工
  2. postProcessAfterInitialization:初始化后方法,表示可以利用这个方法来对Bean在初始化之后进行自定义加工

InstantiationAwareBeanPostProcessorAdapter

  1. postProcessBeforeInstantiation:实例化前
  2. postProcessAfterInstantiation:实例化后
  3. postProcessProperties:属性注入后

FactoryBean

他是Spring所提供的一种比较灵活的创建bean的方式,可以通过实现这个接口中的getObject()方法来返回一个对象,这个对象就是最终的bean对象

主要应用在Spring内部和Spring与第三方框架或组件的整合过程中

其中的方法

  1. getobject():返回bean对象
  2. getobjectType() :返回bean对象类型
  3. idSingleton():是否为单例对象

ApplicationContext(应用程序情况)

为应用程序提供配置的中央接口,BeanFactory的升级版可以创建bean,获取bean,支持国际化,事件广播,获取资源等

继承的接口

  1. EnvironmentCapable:通过这个接口拥有了获取环境变量的功能,可以通过applicationCOntext获取操作系统环境变量和JVM环境变量
  2. ListableBeanFactory:拥有了获得所有beanNames,判断某个beanName是否存在beanDefinition对象,统计beanDefinition个数,获取某个类型对应的所beanName等功能
  3. HierarchicalBeanFactory:获取父beanFactory,判断某个name是否存在bean对象
  4. MessageSource:拥有了国际化的功能,直接使用MessageSource对象获取某个国际化资源
  5. ApplicationEventPublisher:拥有了事件发布功能,可以发布事件
  6. ResourcePatternResolver: 拥有了加载并获取资源的功能,资源可以是文件,图片等某个URL的资源都可以

AbstractAutowireCapableBeanFactory-docreatBean创建Bean实例

	protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
			throws BeanCreationException {

		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
            //factoryBeanInstanceCache:存的是beanname对应factorybean实例对象
            //factoryBeanObjectCache:存的是beanname对应factorybean.getObject返回的实例对象
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
        //2.实例化
		if (instanceWrapper == null) {
            //创建bean实例 new 类名()
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
        //原始对象
		final 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 {
                    //运行修改好了的BeanDefinition
                    //这里会查找@Autowired的注入点
					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.
		//如果当前创建的是单例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");
			}
            //此时的bean还没有完成属性注入,是一个非常简单的对象
            //构造一个对象工厂添加到singletonFactories中
            //第四次调用后置处理器
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
        //对象已经暴露出去了
		Object exposedObject = bean;
		try {
            //3,填充属性@Autowired
			populateBean(beanName, mbd, instanceWrapper);
            //4,初始化和BeanPostProcessor 正常AOP 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) {
			Object earlySingletonReference = getSingleton(beanName, false);
			if (earlySingletonReference != null) {
				if (exposedObject == bean) {
					exposedObject = earlySingletonReference;
				}
				else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
					String[] dependentBeans = getDependentBeans(beanName);
					Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
					for (String dependentBean : dependentBeans) {
						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.
		try {
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
		}

		return exposedObject;
	}
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);
			}
		}
	}
	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        //先看单例池里有没有
		Object singletonObject = this.singletonObjects.get(beanName);
        //没有的话并且当前的bean正在创建中  就是一个Set集合
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			synchronized (this.singletonObjects) {
                //从二级缓存中找
				singletonObject = this.earlySingletonObjects.get(beanName);
                //二级还没有的话
				if (singletonObject == null && allowEarlyReference) {
                    //从三级缓存去找
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                    //
					if (singletonFactory != null) {
						singletonObject = singletonFactory.getObject(); //执行lambda AOP, 结果就是AOP的代理对象
						//然后把他放到二级缓存中 
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        //放到二级缓存之后,再把三级缓存中的删掉:由因结果后,因该删除
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}

AutowiredAnnotationBeanPostProcessor实现了自动装配的功能

实现 自动装配带注释的字段、setter 方法和任意配置方法要注入的此类成员通过 Java 5 注释检测:默认情况下,Spring 的 {@link Autowired @Autowired} 和 {@link Value @Value} 注释。

PlaceholderConfigurerSupport类实现了BeanFactoryPostProcessor

可以替换xml中占位符的内容通过配置文件中定义好的对应值

1. ClassPathXmlApplicationContext

public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {
    private Resource[] configResources;
    public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
        this(new String[]{configLocation}, true, (ApplicationContext)null);
    }//我们使用的时候就是这个构造方法
    public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException {//然后具体使用这个构造方法
        super(parent);//根据提供的路径,处理成配置文件数组(以分号、逗号、空格、tab、换行符分割)
        this.setConfigLocations(configLocations);//设置配置文件的位置
        if (refresh) {
            this.refresh(); //核心方法
        }
    }
}

2.AbstractApplicationContext

public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext, DisposableBean {
public void refresh() throws BeansException, IllegalStateException {
        synchronized(this.startupShutdownMonitor) { //来个锁,不然 refresh() 还没结束,你又来个启动或销毁容器的操作,那不就乱套了嘛,保证同一时间一个执行
            this.prepareRefresh(); // 准备工作,记录下容器的启动时间、标记“已启动”状态、处理配置文件中的占位符
            
            //刷新bean工厂,关闭上一个,开启下一个
            // 这步比较关键,这步完成后,配置文件就会解析成一个个 Bean 定义,注册到 BeanFactory 中,
      // 当然,这里说的 Bean 还没有初始化,只是配置信息都提取出来了,
      // 注册也只是将这些信息都保存到了注册中心(说到底核心是一个 beanName-> beanDefinition 的 map)
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
            // 设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean
            this.prepareBeanFactory(beanFactory);	

            try {
               //子类覆盖方法做额外的处理,此处我们一般不做任何扩展工作,
                this.postProcessBeanFactory(beanFactory);
                //调用各种beanfactory处理器
                this.invokeBeanFactoryPostProcessors(beanFactory);
                //注册bean处理器,只是注册功能,真正调用时getbean方法
                this.registerBeanPostProcessors(beanFactory);
                //为上下文初始化message源,不同语言的消息体,国际化处理
                this.initMessageSource();
                //初始化事件监听多路广播器
                this.initApplicationEventMulticaster();
				//留给子类来初始化其他的bean
                this.onRefresh();
                //在所有注册的bean中查找listener bean,注册到消息广播器中
                this.registerListeners();
                //初始化所有的单实例(非懒加载的)
                this.finishBeanFactoryInitialization(beanFactory);
                //完成刷新
                this.finishRefresh();
            } catch (BeansException var5) {
                this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt", var5);
                this.destroyBeans();
                this.cancelRefresh(var5);
                throw var5;
            }
        }
    }
}
 
protected void prepareRefresh() {
        this.startupDate = System.currentTimeMillis(); //记录当前系统时间
        this.active.set(true);
        if (this.logger.isInfoEnabled()) {
            this.logger.info("Refreshing " + this);
        }

        this.initPropertySources();
        this.getEnvironment().validateRequiredProperties();
    }
2.1 prepareRefresh()
protected void prepareRefresh() {
		// Switch to active.
		this.startupDate = System.currentTimeMillis(); //系统时间 
		this.closed.set(false);//一个原子布尔类型标志,表明当前context是否处于关闭状态
		this.active.set(true);//一个原子布尔类型标志,表明当前context是否处于活跃状态

		if (logger.isDebugEnabled()) {
			if (logger.isTraceEnabled()) {
				logger.trace("Refreshing " + this);
			}
			else {
				logger.debug("Refreshing " + getDisplayName());
			}
		}

		// 在上下文环境中初始化任何占位符属性源.
		initPropertySources();

		// Validate that all properties marked as required are resolvable:
		// see ConfigurablePropertyResolver#setRequiredProperties
        //检验属性都得是可解析的
		getEnvironment().validateRequiredProperties();

		// 存储预刷新应用程序侦听器...
		if (this.earlyApplicationListeners == null) {
			this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
		}
		else {
			// Reset local application listeners to pre-refresh state.
			this.applicationListeners.clear();
			this.applicationListeners.addAll(this.earlyApplicationListeners);
		}

		// Allow for the collection of early ApplicationEvents,
		// to be published once the multicaster is available...
		this.earlyApplicationEvents = new LinkedHashSet<>();
	}
protected void initPropertySources() {//通常子类实现
		// 默认什么都不干.
	}

3.ConfigurationClassPostProcessor自动装配的实现

public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
    //根据对应的registry对象生成hashcode值,此对象自会操作一次,如果之前处理过则抛出异常
        int registryId = System.identityHashCode(registry);
        if (this.registriesPostProcessed.contains(registryId)) {
            throw new IllegalStateException("postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
        } else if (this.factoriesPostProcessed.contains(registryId)) {
            throw new IllegalStateException("postProcessBeanFactory already called on this post-processor against " + registry);
        } else {
            //将马上处理的registry对象的id值放到以及处理的集合对象中
            this.registriesPostProcessed.add(registryId);
            this.processConfigBeanDefinitions(registry); //处理配置类的bean定义信息
        }
    }
//构建和验证一个类是否被@Configuration修饰并做相关的解析工作
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
    //创建存放BeanDefinitionHolder对象集合
    List<BeanDefinitionHolder> configCandidates = new ArrayList();
    //当前registry就是DefaultListableBeanFactory,获取所有已经注册BeanDefinition的beanName
     String[] candidateNames = registry.getBeanDefinitionNames();
    .
    .
    .
    do {
        parser.parse(candidates);
        parser.validate();
        Set<ConfigurationClass> configClasses = new LinkedHashSet(parser.getConfigurationClasses());
        configClasses.removeAll(alreadyParsed);
        if (this.reader == null) {
            this.reader = new ConfigurationClassBeanDefinitionReader(registry, 				        this.sourceExtractor, this.resourceLoader, this.environment,         this.importBeanNameGenerator, parser.getImportRegistry());
        }
.
    .
    .
    .
    

}
class ConfigurationClassParser {
     public void parse(Set<BeanDefinitionHolder> configCandidates) {
.
    .
    .
    try {
                if (bd instanceof AnnotatedBeanDefinition) {
                    this.parse(((AnnotatedBeanDefinition)bd).getMetadata(), holder.getBeanName());
                } else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition)bd).hasBeanClass()) {
                    this.parse(((AbstractBeanDefinition)bd).getBeanClass(), holder.getBeanName());
                } else {
                    this.parse(bd.getBeanClassName(), holder.getBeanName());
                }
        .
            .
            .
            .

     }
         
         
     protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
        this.processConfigurationClass(new ConfigurationClass(metadata, beanName));
    }
         
         
     protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
    ........
     
     }
     @Nullable
    protected final ConfigurationClassParser
        .SourceClass doProcessConfigurationClass(ConfigurationClass configClass           ConfigurationClassParser                                                           .SourceClass sourceClass) 
        throws IOException {
        //解析Component注解
        if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
            this.processMemberClasses(configClass, sourceClass);
        }

        //解析PropertySources注解
        Iterator var3 = AnnotationConfigUtils
            .attributesForRepeatable(sourceClass.getMetadata()
                                     , PropertySources.class, PropertySource.class).iterator();

        AnnotationAttributes importResource;
        while(var3.hasNext()) {
            importResource = (AnnotationAttributes)var3.next();
            if (this.environment instanceof ConfigurableEnvironment) {
                this.processPropertySource(importResource);
            } else {
                this.logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() + "]. Reason: Environment must implement ConfigurableEnvironment");
            }
        }

        Set<AnnotationAttributes> componentScans = AnnotationConfigUtils
            .attributesForRepeatable(sourceClass.getMetadata()
                                     , ComponentScans.class, ComponentScan.class);
        if (!componentScans.isEmpty() && !this.conditionEvaluator
            .shouldSkip(sourceClass.getMetadata()
                        , ConfigurationPhase.REGISTER_BEAN)) {
            Iterator var13 = componentScans.iterator();

            while(var13.hasNext()) {
                AnnotationAttributes componentScan = (AnnotationAttributes)var13.next();
                Set<BeanDefinitionHolder> scannedBeanDefinitions = this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
                Iterator var7 = scannedBeanDefinitions.iterator();

                while(var7.hasNext()) {
                    BeanDefinitionHolder holder = (BeanDefinitionHolder)var7.next();
                    BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
                    if (bdCand == null) {
                        bdCand = holder.getBeanDefinition();
                    }

                    if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
                        this.parse(bdCand.getBeanClassName(), holder.getBeanName());
                    }
                }
            }
        }

        this.processImports(configClass, sourceClass, this.getImports(sourceClass), true);
        importResource = AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
        if (importResource != null) {
            String[] resources = importResource.getStringArray("locations");
            Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
            String[] var19 = resources;
            int var21 = resources.length;

            for(int var22 = 0; var22 < var21; ++var22) {
                String resource = var19[var22];
                String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
                configClass.addImportedResource(resolvedResource, readerClass);
            }
        }

        Set<MethodMetadata> beanMethods = this.retrieveBeanMethodMetadata(sourceClass);
        Iterator var17 = beanMethods.iterator();

        while(var17.hasNext()) {
            MethodMetadata methodMetadata = (MethodMetadata)var17.next();
            configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
        }

        this.processInterfaces(configClass, sourceClass);
        if (sourceClass.getMetadata().hasSuperClass()) {
            String superclass = sourceClass.getMetadata().getSuperClassName();
            if (superclass != null && !superclass.startsWith("java") && !this.knownSuperclasses.containsKey(superclass)) {
                this.knownSuperclasses.put(superclass, configClass);
                return sourceClass.getSuperClass();
            }
        }

        return null;
    }
}

单例Bean,单例模式,单例池之间的关系

Bean与对象的关系:

Bean可以称作为一个对象但是对象缺不是一个bean

bean是一个过程,是Spring容器在启动的过程中通过实例化和初始化得到了最终的结果就是填充完属性的创建成功的对象,所以对象要想变成bean就得:

  1. 先通过构造方法得到对象
  2. 进行填充属性

这也就是@Autowired帮我们做的

@Autowired的工作原理:

Spring会先根据属性的类型去Spring容器中找出该类型所有的Bean对象,如果找出来多个,则再根据属性的名字从多个中再确定一个。如果required属性为true,并且根据属性信息找不到对象,则直接抛异常。

​ 那么为什么呢?

  1. 单例bean:单例bean不是在Spring容器中只有一个该类型的对象,可以有多个只是bean的名字是唯一的
  2. 单例模式:只能由一个对象
  3. 单例池:是用来实现单例bean的一个map,场景:获得同一个对象,第一次getbean的时候就把名字和对象放到单例池中,第二次使用同一个名字去拿同一个对象的时候就先从单例池map中拿,key就是beanname,value就是bean对象

当注解写在某个方法上时,Spring再bean生命周期的属性填充阶段,会根据方法的参数类型,参数名字,从Spring容器找到对象当作方法入参,自动反射调用该方法

当加在构造方法上时,Spring会在推断构造方法阶段,选择该构造方法来进行实例化,在反射调用构造方法之前,会先根据方法参数类型,参数名从Spring容器中找到Bean对象,当做构造方法入参

循环依赖的原理

两个bean创建的时候相互依赖

一级缓存:单例池map singletonObjects Map<String, Object> 保存经过了完整生命周期的单例对象
在这里插入图片描述
在这里插入图片描述

添加一个缓冲map里边存着原始对象这样就可以走下去了,但是有一个问题,这个只能是原始对象,里面没有东西。

当我们进行进行到AOP的时候会生成一个代理对象,然后第五步放入单例池的也是这个代理对象,而不是原始对象

解决方法:提前进行AOP
在这里插入图片描述

那么如何要选择过程中要提前AOP呢?

检查是否有循环依赖

那么怎么检查呢?

首先创建集合把要创建的bean放进去,然后在里边会先去这个集合查,如果这个集合理由这个bean 的名字,就证明这个bean正在创建但是现在还需要创建,那么现在就是在循环依赖

在这里插入图片描述

在循环依赖里AOP生成代理对象,

问题:如果一个类里边两个属性值中都有这个类属性,那么如何保证这两个属性中的类对象是一个呢?

解决思路+新加一个map 这就是二级缓存 earlySingletonObjects Map<String, Object> 出现循环依赖的情况下保存的提前的不完整的bean对象

在这里插入图片描述

再来一个map当缓存,在下一个属性创建bean填充需要的属性A是从二级缓存中拿,这样就保证了使用的是一个对象

但是进行AOP的时候需要使用原始对象才能创造出代理对象,那么怎么拿到原始对象呢?

第三级缓存-再加一个map用来放原始对象和Bean name,definition singletonFactories Map<String, ObjectFactory<?>> 用来兜底的,里边是一个lamba表达式,出现了循环依赖,调用了三级缓存他就会提供出一个代理对象

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nKFDEqHM-1629876976634)(file:///C:\Users\彩虹下~1\AppData\Local\Temp\ksohtml4332\wps2.jpg)]
一级缓存使用ConcurrentHashMap,二级,三级使用hashmap,为什么?

concurrentHashMap为什么还需要加锁

AOP原理

AOP的代理对象:

AOP主要是为了在对象执行前后完成一些额外的逻辑,这时候就需要使用这个对象的代理对象来执行test的方法,然后就会执行AOP的前置方法中的业务逻辑,执行完毕后,根据反射的原理使用method.invoke(target,args)再去执行原对象的test方法

这样的一套操作就在方法执行前执行了一套业务逻辑,使用代理对象

AbstractAutoProxyCreator类
	//AService出现了循环依赖,执行lambda表达式执行这个方法
	@Override
	public Object getEarlyBeanReference(Object bean, String beanName) {
		Object cacheKey = getCacheKey(bean.getClass(), beanName); // beanname aservice
        //把这个提前进行AOP的原始对象以及beanname等存进去
		this.earlyProxyReferences.put(cacheKey, bean);
		return wrapIfNecessary(bean, beanName, cacheKey);  //代理对象
	}
	//正常第四步进行AOP的地方
	@Override
	public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
		if (bean != null) {
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
            //这个map存的是那些提前进行了AOP的bean,在上边方法中
            //null!=bean
			if (this.earlyProxyReferences.remove(cacheKey) != bean) {
                //没有提前进行过AOP,是正常的,在此处进行AOP
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}
//如有必要,包装给定的 bean,即如果它有资格被代理
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    //在当前targetSourcedBeans中存在的bean,表示在实例化之前就存在了对象
		if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}
    //当前这个bean不用被代理
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}
    //先判断当前bean需不需要AOP,比如当前bean的类型是pointcut,Advice,Advisor等就不需要AOP
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}

		// Create proxy if we have advice.
    	//获取当前beanclass所匹配的advisors?,判断有没有切面
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    	//如果匹配的不等于null,那么则进行代理,并返回代理对象
		if (specificInterceptors != DO_NOT_PROXY) {
			this.advisedBeans.put(cacheKey, Boolean.TRUE);
            //基于bean对象和Advisor创建代理对象
			Object proxy = createProxy(
					bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
            //存一个代理对象
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}

关于在实例化阶段的循环依赖

因为这是发生在实例化阶段的循环依赖,连第二部都没有走到,直接在第一步的构造方法中循环依赖,所以Spring的三级缓存没有办法,这时候就使用**@Lazy注解**

原因:使用懒加载来延迟Spring加载bean的时间

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值