SpringIOC 容器启动过程 源码分析以及 循环依赖问题
🍀java全知识点学习笔记 思维导图 面试跳槽必备 码云仓库地址 https://gitee.com/vx202158/vx202158.git 🍀
Spring容器启动过程 源码分析 以及如何解决循环依赖问题
1.Spring是什么
Spring是一款轻量级的开发框架 . 简而言之 Spring提高了开发效率 两个核心 IOC 和 AOP
1.1 IOC ( Inversion of Control ) 是什么
*Inversion of Control 控制反转 *
1.1.1 控制了什么
想象一下如果没有使用spring ,我们要创建一个A对象 它 有属性 id name age 等等 我们是不是需要
new A(id,name,age)
而使用了spring框架后 你所需要的组件没有使用过new 吧 那这个对象 又是谁帮我们创建的呢 又是从哪里来的呢
显而易见的是 对象由spring 帮我们创建的 从容器中获取的 这就是"控制" 控制了 对象的创建以及生命周期的管理
1.1.2 反转了什么
又假如 我们要创建对象A 而又依赖于对象B 没有使用Spring我们通常的做法是 在对象A创建之前创建对象B 而使用了Spring之后 Spring容器能帮我们注入对象A所需要的依赖 这就是反转 反转了 对象与对象之间依赖的获取
1.1.3 类比生活
某一天我们想吃辣椒炒肉,我们需要自己去买菜,自己去炒,最后做出来辣椒炒肉 ( new 对象 ) 你需要吃什么,自己动手去做
而现在,我们可以打开美团 ( spring容器 ) 点一份辣椒炒肉 ,美团(忽略商家) 会做好辣椒炒肉 ( 辣椒炒肉不用你炒了 ) ,送到你家 你需要吃什么 美团给你做好,送到指定位置
1.2 AOP 是什么
在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方 式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个 热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑 的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高 了开发的效率。 --- 百度的解释
关于AOP ,就不多说了 该贴重点也不在这
2.Spring容器的启动过程
2.1 三种启动Spring容器的方式
(1) 从类的根路径下加载配置⽂件,创建spring容器
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
(2) 从磁盘路径上加载配置⽂件,创建spring容器
ApplicationContext applicationContext =new FileSystemXmlApplicationContext();
(3) 加载注解配置类,创建spring容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
2.2 启动过程分析 先看图 ( 使用第一种方式 根路径加载配置文件 )
2.2.1 准备工作
2.2.1.1 创建测试类
/** * @author sz * @DATE 2022/2/25 18:20 */ public class TestBean { public TestBean() { System.out.println("testBean构造方法执行了"); } }
2.2.1.2 创建 applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd "> <!-- 创建测试bean对象 --> <bean id="testBean" class="com.qiuri.sz.TestBean"/> </beans>
2.2.1.3 主启动类
/** * Ioc 容器启动过程分析 */ @Test public void testAOP() { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext-----.xml"); TestBean bean = applicationContext.getBean(TestBean.class); }
2.2.2 断点分析
跟进去 来到 ClassPathXmlApplicationContext 类
调用了另外一个构造方法
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException { /** *调用父类构造 */ super(parent); // 2.解析配置文件的路径 setConfigLocations(configLocations); // 3.判断是否需要刷新容器 if (refresh) { //true // 刷新容器 refresh(); } }
最终执行了 refresh()方法
2.2.3 refresh() 方法分析
org.springframework.context.support.AbstractApplicationContext#refresh
首先可以看到 方法第一行就是个同步代码块 解决线程安全问题
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { prepareRefresh(); ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); prepareBeanFactory(beanFactory); try { postProcessBeanFactory(beanFactory); invokeBeanFactoryPostProcessors(beanFactory); registerBeanPostProcessors(beanFactory); initMessageSource(); initApplicationEventMulticaster(); onRefresh(); registerListeners(); finishBeanFactoryInitialization(beanFactory); finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } destroyBeans(); cancelRefresh(ex); throw ex; } finally { // Reset common introspection caches in Spring's core, since we // might not ever need metadata for singleton beans anymore... resetCommonCaches(); } } }
2.2.3.1 prepareRefresh()方法 准备上下文刷新工作,记录容器的启动时间以及状态
protected void prepareRefresh() { // 记录启动时间. this.startupDate = System.currentTimeMillis(); // 设置容器为未关闭状态 this.closed.set(false); // 设置容器为激活状态 this.active.set(true); 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: * 作用:校验属性 */ getEnvironment().validateRequiredProperties(); // Store pre-refresh ApplicationListeners... 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<>(); }
该方法主要是 准备上下文刷新工作,记录容器的启动时间以及状态
2.2.3.2 obtainFreshBeanFactory()方法 创建beanFactory工厂以及 解析创建BeanDefinition对象
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
跟进去
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { refreshBeanFactory(); return getBeanFactory(); }
跟进 refreshBeanFactory()方法
protected final void refreshBeanFactory() throws BeansException { // 看名字 是否有bean工厂存在 if (hasBeanFactory()) { // 如果有bean工厂存在 销毁 bean destroyBeans(); // 关闭bean工厂 closeBeanFactory(); } try { // 创建bean工厂,返回Bean工厂类型是:DefaultListableBeanFactory //return new DefaultListableBeanFactory(getInternalParentBeanFactory()); DefaultListableBeanFactory beanFactory = createBeanFactory(); // 设置序列化ID beanFactory.setSerializationId(getId()); //设置bean是否可以被覆盖以及是否允许循环引用. 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); } }
loadBeanDefinitions(beanFactory) 方法执行前 beanDefinitionMap 为空
loadBeanDefinitions(beanFactory) 方法执行后 beanDefinitionMap 有元素了
其中map的key为 我们xml配置文件中 bean标签的ID 也就是容器中bean的name value 的 beanClass记录了 testBean的全限定类名 com.qiuri.sz.TestBean
在obtainFreshBeanFactory 获取Bean工厂,解析bean定义信息.生成BeanDefinition对象,存入BeanDefinitionMap中
2.2.3.3 prepareBeanFactory(beanFactory)方法 设置bean工厂的属性
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { beanFactory.setBeanClassLoader(getClassLoader()); // 设置SPEL解析器 beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader())); // 添加属性编辑注册器 beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment())); // 添加bean的后置处理器。此处添加的是Spring自己的后置处理器,用来回调bean所实现的aware接口中的方法. beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); // 下面的ignoreDependencyInterface是用来设置bean工厂中需要忽略的接口 beanFactory.ignoreDependencyInterface(EnvironmentAware.class); // 可以通过实现EmbeddedValueResolverAware接口来获取String类型值的解析器 beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class); // 资源加载器,例如使用:@Autowired ResourceLoaderAware aware; 将不会被注入 beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class); // 事件发布器 beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class); // 消息资源 beanFactory.ignoreDependencyInterface(MessageSourceAware.class); // 应用的上下文信息 beanFactory.ignoreDependencyInterface(ApplicationContextAware.class); // 注册一些可以自动装配的接口。 当类型为dependencyType时, 注入autowiredValue。为了解决一个类型有多个子类实现时,优先注入那个子类实现的问题。 // 例如下面第一个,当注入类型为BeanFactory时,注入的值为beanFactory,默认为DefaultListableBeanFactory beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory); // 当注入类型为ResourceLoader时,注入的值为ApplicationContext beanFactory.registerResolvableDependency(ResourceLoader.class, this); // 当注入类型为ApplicationEventPublisher时,注入的值为ApplicationContext beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this); // 当注入的类型为ApplicationContext时,注入的值为ApplicationContext. beanFactory.registerResolvableDependency(ApplicationContext.class, this); // 增加一个bean的后置处理器,ApplicationListenerDetector // Register early post-processor for detecting inner beans as ApplicationListeners. beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this)); // Detect a LoadTimeWeaver and prepare for weaving, if found. // 如果bean工厂中存在着名称为loadTimeWeaver的bean定义,则给bean工厂中加入LoaderTimeWeaverAwareProcessor后置处理器 // 补充:1、增加对AspectJ的支持,在Java中织入分为3种:(1) 编译期织入; (2) 类加载期织入; (3) 运行期织入。编译期织入指的是在java编译期, // 采用特殊的编译器,将切面织入到java类中;类加载期织入则指的是通过特殊的类加载器,在字节码加载到JVM时,织入切面;运行期织入则是 // 通过采用cglib或者jdk进行切面的织入。 // 2、aspectJ中提供了两种方式: // (1) 通过特殊编译器,在编译期,将aspectJ语言编写的切面类织入到java类中; // (2) 类加载期织入,就是通过下面的LoadTimeWeaving if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); // Set a temporary ClassLoader for type matching. beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } // 给容器中注册一些与运行环境相关的单实例Bean if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) { // beanName: environment,直接将new出来的Spring内部对象放入到Spring的单实例缓存池中. beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment()); } if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) { // beanName: systemProperties 方法:System.getProperties(); beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties()); } if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) { // beanName: systemEnvironment, 方法:System.getEnv(); beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment()); } }
2.2.3.4 postProcessBeanFactory(beanFactory) 空方法,bean定义信息加载完成后执行,可以用来修改beanFactory中定义的bean定义信息
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { }
2.2.3.5 invokeBeanFactoryPostProcessors(beanFactory) 执行 BeanFactory的后置处理器方法
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) { // 执行Bean工厂的所有后置处理器 PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()); if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } }
我们没有BeanFactory的后置处理器,所以方法跟进去后if判断直接跳过
2.2.3.6 registerBeanPostProcessors(beanFactory) 注册(不是执行)Bean的后置处理器
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) { PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);}
2.2.3.7 initMessageSource() 消息国际化
protected void initMessageSource() { // 获取bean工厂 ConfigurableListableBeanFactory beanFactory = getBeanFactory(); // 判断是否在bean工厂中定义了id为messageSource的bean对象 if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) { // 如果有id为messageSource,而且类型是MessageSource的组件,直接赋值给messageSource属性 this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class); // Make MessageSource aware of parent MessageSource. if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) { HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource; if (hms.getParentMessageSource() == null) { // Only set parent context as parent MessageSource if no parent MessageSource // registered already. hms.setParentMessageSource(getInternalParentMessageSource()); } } if (logger.isTraceEnabled()) { logger.trace("Using MessageSource [" + this.messageSource + "]"); } } else { // Use empty MessageSource to be able to accept getMessage calls. // 如果没有,则创建一个DelegatingMessageSource类型的messageSource对象 DelegatingMessageSource dms = new DelegatingMessageSource(); dms.setParentMessageSource(getInternalParentMessageSource()); this.messageSource = dms; // 将messageSource注册到容器中,在获取国际化配置文件中的某个值时,可以直接通过注入MessageSource, // 调用其getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale)方法来获取. beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource); if (logger.isTraceEnabled()) { logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]"); } } }
2.2.3.8 initApplicationEventMulticaster() 初始化上下文事件派发器
protected void initApplicationEventMulticaster() { // 获取Bean工厂 ConfigurableListableBeanFactory beanFactory = getBeanFactory(); // APPLICATION_EVENT_MULTICASTER_BEAN_NAME = applicationEventMulticaster // 判断当前的bean工厂中有没有id为applicationEventMulticaster的事件派发器 if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) { // 如果有,则直接获取到ApplicationEventMulticaster类型的事件多播器,并赋值给applicationEventMulticaster. this.applicationEventMulticaster = beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class); if (logger.isTraceEnabled()) { logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]"); } } else { // 如果没有则创建一个类型为SimpleApplicationEventMulticaster事件监听器, this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory); // 将创建的事件多播器注册到容器中,在其他组件需要派发事件时,直接获取这个applicationEventMulticaster beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster); if (logger.isTraceEnabled()) { logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " + "[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]"); } } }
2.2.3.9 ionRefresh() 初始化特殊的Bean,通过继承AbstractApplicationContext类,重写该方法完成自定义特殊bean的初始化.
protected void onRefresh() throws BeansException { //空,什么也没有,留给我们去实现 SpringBoot也是在改步骤中启动内嵌Tomcat容器的 }
2.2.3.10 registerListeners() 注册监听器
protected void registerListeners() { // 将注册的监听器绑定到广播器 for (ApplicationListener<?> listener : getApplicationListeners()) { getApplicationEventMulticaster().addApplicationListener(listener); } // 根据类型获取listener监听器的名称 String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false); for (String listenerBeanName : listenerBeanNames) { // 将事件监听器注册到派发器中,以后使用的时候,就可以直接通过事件派发器执行. getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName); } /** * 派发之前产生的事件。 * earlyApplicationEvent是在prepareRefresh中声明的. */ Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents; this.earlyApplicationEvents = null; if (earlyEventsToProcess != null) { for (ApplicationEvent earlyEvent : earlyEventsToProcess) { getApplicationEventMulticaster().multicastEvent(earlyEvent); } } }
2.2.3.11 finishBeanFactoryInitialization(beanFactory) 初始化所有的单例bean (核心)
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { // 1. 初始化此上下文的转换服务,用来自定义将Spring中的某个Bean的属性从一个类型转换到另外一个类型. // 判断Bean工厂中是否存在名称为conversionService的转换服务bean,如果存在而且类型为ConversionService,则获取该Bean实例,并将其设置到BeanFactory中 if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) && beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) { beanFactory.setConversionService(beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)); } if (!beanFactory.hasEmbeddedValueResolver()) { // 调用resolvePlaceholders方法解析strVal对应的值 beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal)); } String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false); for (String weaverAwareName : weaverAwareNames) { getBean(weaverAwareName); } // 停止使用临时的类加载器. beanFactory.setTempClassLoader(null); // 缓存(冻结)所有的BeanName(注册的bean定义不会被修改或进一步做处理了,因为下面马上要创建Bean的实例对象了) beanFactory.freezeConfiguration(); // 初始化所有的单实例Bean,包括创建单实例bean的全部过程 beanFactory.preInstantiateSingletons(); }
直接看 beanFactory.preInstantiateSingletons()方法 跟进去
public void preInstantiateSingletons() throws BeansException { if (logger.isTraceEnabled()) { logger.trace("Pre-instantiating singletons in " + this); } // 创建beanName集合 List<String> beanNames = new ArrayList<>(this.beanDefinitionNames); // 遍历所有的beanNames,创建所有的单实例Bean for (String beanName : beanNames) { // 获取beanName对应的MergedBeanDefinition. BeanDefinitionMap的value key为beanName 不记得了可以看 2.2.3.2 RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); // 如果bd对应的Bean实例满足:(不是抽象类 && 是单例 && 不是懒加载) if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { // 判断BeanName对应的Bean实例是否是FactoryBean. if (isFactoryBean(beanName)) { // 通过beanName获取FactoryBean的实例,factoryBean的名称是:"&" + beanName Object bean = getBean(FACTORY_BEAN_PREFIX + beanName); if (bean instanceof FactoryBean) { final FactoryBean<?> factory = (FactoryBean<?>) bean; boolean isEagerInit; // 判断这个FactoryBean是否需要紧急初始化. 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) { // 如果需要紧急初始化,则通过beanName获取Bean的实例. getBean(beanName); } } } else { // 如果BeanName对应的Bean实例不是FactoryBean,则通过BeanName去获取Bean实例. getBean(beanName); } } } /** * 上一步for循环中已经创建完了所有的单实例Bean,这个for循环中,会拿出所有的单实例Bean, * 然后遍历,判断单实例bean是否实现了SmartInitializingSingleton接口,如果实现了该接口, * 则调用单实例Bean的afterSingletonsInstantiated方法 */ for (String beanName : beanNames) { // 获取beanName对应的bean实例 Object singletonInstance = getSingleton(beanName); // 判断当前的bean是否实现了SmartInitializingSingleton接口. if (singletonInstance instanceof SmartInitializingSingleton) { final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance; // 触发SmartInitializingSingleton实现类的afterSingletonInstantiated方法. if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { smartSingleton.afterSingletonsInstantiated(); return null; }, getAccessControlContext()); } else { /** * 如果实现了SmartInitializingSingleton接口,则会调用afterSingletonInstantiated方法 * 例如@EventListener注解的实现原理,就是利用EventListenerMethodProcessor后置处理器完成的, * 而在EventListenerMethodProcessor中就是实现了SmartInitializingSingleton接口 */ smartSingleton.afterSingletonsInstantiated(); } } } }
跟进getBean(beanName)方法 org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)
@Override public Object getBean(String name) throws BeansException { // 空方法 return doGetBean(name, null, null, false); }
继续跟进 doGetBean方法 org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean ( Spring循环依赖问题在此解决)
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException { // 获取真正的BeanName。主要包括: 去掉FactoryBean名称前面的&前缀;(2) bean别名解析; final String beanName = transformedBeanName(name); Object bean; // 先尝试从缓存中获取单实例Bean,如果能获取到,说明已经被创建过 // 注意:如果是通过FactoryBean方式创建对象。在根据名称获取目标bean对象(非FactoryBean实例)时,此处返回的sharedInstance是FactoryBean对象 Object sharedInstance = getSingleton(beanName); /** * 当组件实现了FactoryBean接口,并重写了getObject方法时。在从容器中获取bean的时候,sharedInstance就是容器中返回的bean对象 * 此时sharedInstance不为空,就会调用getObjectForBeanInstance方法,这个方法内部会调用子类重写的getObject方法. */ if (sharedInstance != null && args == null) { if (logger.isTraceEnabled()) { if (isSingletonCurrentlyInCreation(beanName)) { logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference"); } else { logger.trace("Returning cached instance of singleton bean '" + beanName + "'"); } } // 获取bean对象,包括使用FactoryBean来创建bean的逻辑. bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { // 如果当前创建的是单实例类型的bean,则尝试解决循环依赖,此处仅仅只是一个校验;如果当前的多实例bean正在创建中,而且存在循环依赖,直接抛出异常 if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } // 获取Bean的父工厂 BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { // Not found -> check parent. String nameToLookup = originalBeanName(name); if (parentBeanFactory instanceof AbstractBeanFactory) { return ((AbstractBeanFactory) parentBeanFactory).doGetBean( nameToLookup, requiredType, args, typeCheckOnly); } else if (args != null) { // Delegation to parent with explicit args. return (T) parentBeanFactory.getBean(nameToLookup, args); } else if (requiredType != null) { // No args -> delegate to standard getBean method. return parentBeanFactory.getBean(nameToLookup, requiredType); } else { return (T) parentBeanFactory.getBean(nameToLookup); } } // 标记Bean已经被创建,防止多线程时,Bean可能会被创建多个,就不是单实例了 if (!typeCheckOnly) { // 将beanName对应的bean定义从mergedBeanDefinitions中移除,并将beanName添加到alreadyCreated集合中. markBeanAsCreated(beanName); } try { // 获取合并之后的Bean定义 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); // 校验bean对应的类是否为抽象的,如果bean对应的类标注了抽象,直接会抛出异常 checkMergedBeanDefinition(mbd, beanName, args); /** * 获取当前Bean所依赖的其他Bean 解决循环依赖问题 */ String[] dependsOn = mbd.getDependsOn(); // 如果有依赖的Bean if (dependsOn != null) { for (String dep : dependsOn) { if (isDependent(beanName, dep)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } // 维护依赖和被依赖的bean之间的关联关系 registerDependentBean(dep, beanName); try { // 先去创建当前bean所依赖的其他bean对象 getBean(dep); } catch (NoSuchBeanDefinitionException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", ex); } } } // bean定义如果是单例的,则调用createBean方法进行单实例bean的创建. if (mbd.isSingleton()) { // 此处的lambda表达式为:ObjectFactory的getObject方法 sharedInstance = getSingleton(beanName, () -> { try { /** * 创建对象并初始化,Spring用来创建Bean实例的核心方法 * 此处调用的子类AbstractAutowireCapableBeanFactory的createBean方法. */ return createBean(beanName, mbd, args); } catch (BeansException ex) { // 如果创建单实例bean失败,则会删除关于该bean的一切信息,包括三级缓存和已经注册的bean集合中有关该bean的信息 destroySingleton(beanName); throw ex; } }); /** * 如果一个类实现了FactoryBean接口,回调FactoryBean的getObject自定义方法进行应用bean的创建工作 */ bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } // 当前需要创建的bean如果是多例 else if (mbd.isPrototype()) { // 创建多实例bean Object prototypeInstance; try { // 进行多实例bean创建之前的准备工作,将当前正在创建的多实例bean的名称添加到prototypesCurrentlyInCreation中. beforePrototypeCreation(beanName); // 创建多实例对象,和创建单实例bean使用的是同一个方法 prototypeInstance = createBean(beanName, mbd, args); } finally { // 从prototypesCurrentlyInCreation【ThreadLocal】中移除 afterPrototypeCreation(beanName); } bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } // 未明确指定将要创建的bean是单例的还是多例的 else { String scopeName = mbd.getScope(); // 从bean定义中获取bean的scope信息,如果bean的scope信息为null,也就是随意设置的scope,直接抛出异常 final Scope scope = this.scopes.get(scopeName); if (scope == null) { throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'"); } try { // 根据指定的scope获取bean实例 Object scopedInstance = scope.get(beanName, () -> { // 初始化之前准备工作,将bean的名称添加到prototypesCurrentlyInCreation beforePrototypeCreation(beanName); try { // 创建bean实例 return createBean(beanName, mbd, args); } finally { // 从prototypesCurrentlyInCreation中移除 afterPrototypeCreation(beanName); } }); bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); } catch (IllegalStateException ex) { throw new BeanCreationException(beanName, "Scope '" + scopeName + "' is not active for the current thread; consider " + "defining a scoped proxy for this bean if you intend to refer to it from a singleton", ex); } } } catch (BeansException ex) { cleanupAfterBeanCreationFailure(beanName); throw ex; } } /** * 判断是否需要将bean转换为我们指定类型的Class,如果需要转换,则使用自定义的TypeConverter进行bean类型的转换 * 如果未指定TypeConverter,则默认使用SimpleTypeConverter,converter需要设置一个用来转化的Service实现类,即:ConversionService, * ConversionService是在finishBeanFactoryInitialization方法的最前面进行注册的,可以在xml中配置对应的ConversionService实现类 */ if (requiredType != null && !requiredType.isInstance(bean)) { try { T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType); if (convertedBean == null) { throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } return convertedBean; } catch (TypeMismatchException ex) { if (logger.isTraceEnabled()) { logger.trace("Failed to convert bean '" + name + "' to required type '" + ClassUtils.getQualifiedName(requiredType) + "'", ex); } throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } } return (T) bean; }
跟进 createBean(beanName, mbd, args)方法 创建实例对象
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { // Instantiate the bean. BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { // 删除之前工厂bean缓存中的工厂bean对象,重新进行实例化. instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } // 创建Bean的实例,并且包装为一个包装对象返回. if (instanceWrapper == null) { // 使用策略方法创建实例,包括:工厂方法,构造函数注入,简单初始化. // TODO 里面调用的方法超级长 instanceWrapper = createBeanInstance(beanName, mbd, args); } // 获取新创建的bean对象和对应的class 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) { // 如果还未执行MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition方法 if (!mbd.postProcessed) { try { // 依次调用所有MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition方法,用来处理类中使用注解标注的属性,并放入到缓存中. /** * 其中包括了 * 【AutowiredAnnotationBeanPostProcessor】, 用来处理@Autowired,@Value,@Inject注解 * 【CommonAnnotationBeanPostProcessor】, 用来处理@Resource注解 * 【RequiredAnnotationBeanPostProcessor】, 用来处理@Required注解 * 【InitDestroyAnnotationBeanPostProcessor】,用来处理@Predestroy和@PostConstruct注解 * 【ScheduledAnnotationBeanPostProcessor】,用来处理@Scheduled注解 * 等后置处理器 */ 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是单例的 && 允许bean之间的循环依赖 && bean正在创建中 */ boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); // 判断是否需要提前暴露自己。如果需要提前暴露,会将创建完但未填充属性和初始化的bean放入到singletonFactories中,用来解决循环依赖. // Spring中的单实例Bean,而且是使用属性注入的方式,默认支持循环依赖的;如果是prototype类型的,默认不支持循环依赖 // 如果是单例bean,而且使用构造器注入的方式,默认不支持循环依赖,可在构造器上添加@Lazy注解,让依赖的属性延迟初始化来解决 // 如果是单例bean和prototype类型的bean混用,则如果先创建单例,可以成功,如果先创建prototype类型的bean,则会失败 if (earlySingletonExposure) { if (logger.isTraceEnabled()) { logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } /** * getEarlyBeanReference: 是用来获取到被SmartInstantiationAwareBeanPostProcessor后处理器处理过的刚刚实例化结束的bean对象 * * addSingletonFactory: 是用来将刚刚初始化的bean对象放入到singletonFactories中,singletonFactories是个map集合, * key: bean的名称,value: 是一个ObjectFactory,当存在着循环依赖时,可以通过ObjectFactory.getObject方法获取到刚刚实例化的bean对象 */ addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } /** 初始化单实例bean。 包括:填充属性及执行初始化方法 */ Object exposedObject = bean; try { /** * 【依赖注入】 * 填充的属性包括:普通属性和使用@Autowired和@Resource注解标注的引用类型属性的赋值。使用了反射操作set方法完成赋值. * * eg: 重点操作举例: * 【创建完成Bean之后,填充Bean的属性,填充过程中会调用InstantiationAwareBeanPostProcessorAdaptor类的postProcessProperties方法】 */ populateBean(beanName, mbd, instanceWrapper); /** * 完成Bean的初始化(执行afterPropertiesSet和init-method) * 注意:会调用@PostConstruct标注的方法,这个方法是在Bean创建完成,而且属性填充完成之后,才会被调用 */ 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."); } } } } try { /** * 注册bean的销毁方法,如果bean不是prototype类型,而且requiresDestruction方法返回true * 则会将当前的bean放入到一个需要被销毁的map集合中. */ registerDisposableBeanIfNecessary(beanName, bean, mbd); } catch (BeanDefinitionValidationException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex); } return exposedObject; }
*addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); * 把实例对象放入三级缓存中
getSingleton(String beanName) 缓存中获取Bean (解决循环依赖)
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String)
public Object getSingleton(String beanName) { // 从缓存中获取单实例Bean return getSingleton(beanName, true); }
继续根据 getSingleton(beanName, true);
protected Object getSingleton(String beanName, boolean allowEarlyReference) { //首先从一级缓存 singletonObjects中 尝试获取bean Object singletonObject = this.singletonObjects.get(beanName); // 一级缓存中都是以及初始化完成的单例bean 如果一级没有,可能在二级缓存 earlySingletonObjects 也就是半成品bean 正在初始化的 if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { // 加锁操作. synchronized (this.singletonObjects) { //尝试从二级缓存中获取半成品bean singletonObject = this.earlySingletonObjects.get(beanName); // 如果早二级缓存中没有,而且允许创建早期单实例对象引用 if (singletonObject == null && allowEarlyReference) { // 则从三级缓存中获取BeanName对应的单例工厂. ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { // 如果存在着单例对象工厂,则通过工厂创建一个单例对象, // 调用的是:addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean))中的lombda表达式 singletonObject = singletonFactory.getObject(); // 将单例工厂对象创建的bean放到二级缓存 earlySingletonObjects中 this.earlySingletonObjects.put(beanName, singletonObject); // 删除三级缓存中的bean对应的工厂对象 this.singletonFactories.remove(beanName); } } } } //返回bean单例对象 return singletonObject; }
3.循环依赖问题
3.1什么是循环依赖
依赖注入的时候 ,发现A 依赖于B 而B依赖注入的时候发现依赖于A 两者都需要依赖于对方完成属性注入
3.2 Spring中的三级缓存
一级缓存 singletonObjects 存放已经完成实例化的单例bena 本质是一个 ConcurrentHashMap
二级缓存 earlysingletonObjects 存放半成品单例Bean ( 已经实例化,未完成初始化 ) 本质是一个 HashMap
三级缓存 singletonFactorie 存放bean工厂对象 本质是一个HashMap
源码 可以看 getSingleton(String beanName) 缓存中获取Bean
3.3 spring是如何解决循环依赖的
sping在初始化一个bean对象时,会看这个bean是有有依赖的其他bean ,如果有 先初始化依赖的bean ,依赖的bean对象完成初始化后,再来初始化当前bean
具体详细过程:
1,A创建过程中需要B,于是A将自己放到三级缓里面,去实例化B
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
2,B实例化的时候发现需要A,于是B先查一级缓存,没有,再查二级缓存,还是没有,再查三级缓存,找到了A然后把三级缓存里面的这个A放到二级缓存里面,并删除三级缓存里面的A
3,B顺利初始化完毕,将自己放到一级缓存里面(此时B里面的A依然是创建中状态)
然后回来接着创建A,此时B已经创建结束,直接从一级缓存里面拿到B,然后完成创建,并将A自己放到一级缓存里面。
#Java求职##学习路径##Spring##Java##笔试题目##面经##春招##实习#