package com.yueny.fw.practice.spring; import com.yueny.fw.practice.lock.Deadlock; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @Author yueny09 <deep_blue_yang@126.com> * @Date 2019-10-21 14:10 */ public class ApplicationMain { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext( "classpath:/config/spring-bean.xml"); Deadlock deadlock = context.getBean("deadlock", Deadlock.class); System.out.println(deadlock.toString()); } } 复制代码
见《Spring获取Bean的流程(二)》ClassPathXmlApplicationContext 加载器的时序图
ClassPathXmlApplicationContext 的构造器中调用类同名方法:
public ClassPathXmlApplicationContext(String configLocation) throws BeansException { this(new String[] {configLocation}, true, null); } 复制代码
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException { // super()方法是一直到父类AbstractXmlApplicationContext --> AbstractRefreshableConfigApplicationContext --> AbstractRefreshableApplicationContext --> AbstractApplicationContext 中,将ApplicationContext的环境属性设置给本类的环境属性,包括一些profile,系统属性等. // 执行了 getEnvironment().merge 合并操作 super(parent); setConfigLocations(configLocations); // 调用父类方法,将xml配置文件地址名字给父类的String数组属性 if (refresh) { refresh(); // 进行初始化,所有的逻辑其实都在这个方法里面进行 } } 复制代码
ClassPathXmlApplicationContext中的refresh方法,实际上调用的是父类org.springframework.context.support.AbstractApplicationContext的方法。
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // 在刷新之前设置一些参数,比如设置开始时间戳,上下文是否激活的标志,输出刷新上下文的信息,验证一些必要的属性, 见 3.1 // Prepare this context for refreshing. prepareRefresh(); // 这步完成后,配置文件就会解析成一个个 Bean 定义,注册到 BeanFactory 中, // 当然,这里说的 Bean 还没有初始化,只是配置信息都提取出来了, // 注册也只是将这些信息都保存到了注册中心(说到底核心是一个 beanName-> beanDefinition 的 map) // 详情见3.2及3.2.* ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean,详情见 3.4 // Prepare the bean factory for use in this context. prepareBeanFactory(beanFactory); // prepareBeanFactory()方法调用之后,是一个try-catch代码块,如果有BeanException异常产生则会停止refresh并且销毁已创建的资源 try { // 获取容器级别的后处理器,允许上下文的子类中对beanFactory进行后处理,在应用上下文内部beanFactory初始化之后可以修改beanFactory,此时所有的BeanDefinittions都已经被加载,但未被实例化,具体的实现在AbstractRefreshableWebApplicationContext // 默认方法体是空的,主要是用来扩展beanfactory的,扩展点是在bean等配置都已经加载但还没有进行实例化的时候。 // 到这里的时候,所有的 Bean 都加载、注册完成了,但是都还没有初始化 postProcessBeanFactory(beanFactory); // 详情见 3.5 // 调用BeanFactoryPostProcessor和BeanDefintionRegistoryPostProcessor这两个后置处理器 // Invoke factory processors registered as beans in the context. invokeBeanFactoryPostProcessors(beanFactory); // 详情见 3.5 // 注册BeanPostProcessor 后置处理器,用来拦截bean的创建,详情见 xxx // 注意,到这里 Bean 还没初始化 registerBeanPostProcessors(beanFactory); // 详情见 3.6 // 初始化消息源 // Initialize message source for this context. initMessageSource(); // 初始化应用程序事件广播器,用户可以自定义一个事件广播器,如果用户没有定义,那么使用默认的事件广播器SimpleApplicationEventMulticaster // Initialize event multicaster for this context. initApplicationEventMulticaster(); // 空方法由子类扩展,可以在实例化bean之前做一些ApplicationContext相关的操作 // Initialize other special beans in specific context subclasses. onRefresh(); // 注册和检测事件监听器 // Check for listener beans and register them. registerListeners(); //单例模式的bean实例化,初始化(non-lazy-init),即所有单例非懒加载Bean的调用点 // 重点,重点,重点 // 初始化所有的 singleton beans (lazy-init 的除外) // 详见 3.7 finishBeanFactoryInitialization(beanFactory); // applicationContext刷新完成后的处理,例如生命周期监听器的回调,广播通知等 // Last step: publish corresponding event. finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } // Destroy already created singletons to avoid dangling resources. destroyBeans(); // Reset 'active' flag. cancelRefresh(ex); // Propagate exception to caller. throw ex; } finally { // Reset common introspection caches in Spring's core, since we // might not ever need metadata for singleton beans anymore... resetCommonCaches(); } } } 复制代码
prepareRefresh();
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { // 执行的为 ClassPathXmlApplicationContext 的父类方法 AbstractRefreshableApplicationContext //实际刷新上下文的方法,这个方法就是实际的刷新上下文方法,其中会调用loadBeanDefinitions(beanFactory)加载配置文件中的内容到BeanDefiniton中。 详见下述代码段 refreshBeanFactory(); ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (logger.isDebugEnabled()) { logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory); } return beanFactory; } 复制代码
refreshBeanFactory(): org.springframework.context.support.AbstractRefreshableApplicationContext中的方法
protected final void refreshBeanFactory() throws BeansException { // 如果BeanFactory存在就销毁关闭,在后续逻辑中重新创建 if (hasBeanFactory()) { destroyBeans(); // 将BeanFactory设置为null,序列化id设置为null closeBeanFactory(); } try { /** * 创建DefaultListableBeanFactory, * 此类是整个Bean加载的核心部分,是Spring注册加载Bean的默认实现,是整个Spring IOC的始祖. * 对beanFactory进行设置,bean注册等操作,最后将beanFactory赋值给本类的beanFactory属性 */ /* 我们看《BeanFactory 接口相关的继承结构》图可以看出,ConfigurableListableBeanFactory 只有一个实现类 DefaultListableBeanFactory,而且实现类 DefaultListableBeanFactory 还通过实现右边的 AbstractAutowireCapableBeanFactory 通吃了右路。 */ DefaultListableBeanFactory beanFactory = createBeanFactory(); beanFactory.setSerializationId(getId()); // 由AbstractRefreshableApplicationContext实现, // 设置 BeanFactory 的两个配置属性:是否允许 Bean 覆盖、是否允许循环引用 customizeBeanFactory(beanFactory); // 加载 Bean 到 BeanFactory 中, 即Bean的注册, 此处实现类为 AbstractXmlApplicationContext,详情见 3.2.1 loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } } 复制代码
3.2.1 AbstractXmlApplicationContext 类中的 loadBeanDefinitions(beanFactory);
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException { //创建要给beanDefinitionReader,用于读取BeanDefinition // Create a new XmlBeanDefinitionReader for the given BeanFactory. XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); // Configure the bean definition reader with this context's // resource loading environment. // 然后设置环境属性以及 资源加载器ResourceLoader 为this(实际为 ClassPathXmlApplicationContext) beanDefinitionReader.setEnvironment(this.getEnvironment()); beanDefinitionReader.setResourceLoader(this); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); // 接着初始化读取器 initBeanDefinitionReader,其实这个是提供给子类覆写的 // Allow a subclass to provide custom initialization of the reader, // then proceed with actually loading the bean definitions. initBeanDefinitionReader(beanDefinitionReader); // 加载BeanDefiniton,主要的功能从配置文件中读取BeanDefiniton注册到注册表中。详见 3.2.2 loadBeanDefinitions(beanDefinitionReader); } 复制代码
3.2.2 AbstractXmlApplicationContext 类中的 loadBeanDefinitions(beanDefinitionReader)
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException { Resource[] configResources = getConfigResources(); // 加载资源 if (configResources != null) { reader.loadBeanDefinitions(configResources); } String[] configLocations = getConfigLocations(); // 加载之前设置的xml配置文件资源 if (configLocations != null) { // 循环加载xml文件的Bean返回Bean总个数,详见 3.2.3 reader.loadBeanDefinitions(configLocations); } } 复制代码
3.2.3 XmlBeanDefinitionReader 类中的 loadBeanDefinitions
public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException { ResourceLoader resourceLoader = getResourceLoader(); if (resourceLoader == null) { throw new BeanDefinitionStoreException( "Cannot import bean definitions from location [" + location + "]: no ResourceLoader available"); } if (resourceLoader instanceof ResourcePatternResolver) { // Resource pattern matching available. try { // 获取加载器中的Resource[] 数组 Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location); // 查看loadBeanDefinitions,循环加载所有的资源,返回总数资源中的Bean int loadCount = loadBeanDefinitions(resources); if (actualResources != null) { for (Resource resource : resources) { actualResources.add(resource); } } if (logger.isDebugEnabled()) { logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]"); } return loadCount; } catch (IOException ex) { throw new BeanDefinitionStoreException( "Could not resolve bean definition resource pattern [" + location + "]", ex); } } else { // Can only load single resources by absolute URL. Resource resource = resourceLoader.getResource(location); // 详见 3.2.4 int loadCount = loadBeanDefinitions(resource); if (actualResources != null) { actualResources.add(resource); } if (logger.isDebugEnabled()) { logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]"); } return loadCount; } } 复制代码
3.2.4 loadBeanDefinitions讲解
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException { Assert.notNull(encodedResource, "EncodedResource must not be null"); if (logger.isInfoEnabled()) { logger.info("Loading XML bean definitions from " + encodedResource.getResource()); } // resourcesCurrentlyBeingLoaded 定义为 new NamedThreadLocal<Set<EncodedResource>>, // 这里对正在解析的xml资源放入ThreadLocal中,保证只有本次线程可以访问,加载完之后再移除. 保证并发和同步 Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get(); if (currentResources == null) { currentResources = new HashSet<EncodedResource>(4); this.resourcesCurrentlyBeingLoaded.set(currentResources); } // 先添加进 threadLocal, 加载完成之后 finally 中再移除 threadLocal if (!currentResources.add(encodedResource)) { throw new BeanDefinitionStoreException( "Detected cyclic loading of " + encodedResource + " - check your import definitions!"); } try { InputStream inputStream = encodedResource.getResource().getInputStream(); try { InputSource inputSource = new InputSource(inputStream); if (encodedResource.getEncoding() != null) { inputSource.setEncoding(encodedResource.getEncoding()); } // 此处 解析 Document, 并在解析之后进行注册(bean的注册方法 registerBeanDefinitions(Document doc, Resource resource),详见 详见 3.3) return doLoadBeanDefinitions(inputSource, encodedResource.getResource()); } finally { inputStream.close(); } } catch (IOException ex) { throw new BeanDefinitionStoreException( "IOException parsing XML document from " + encodedResource.getResource(), ex); } finally { currentResources.remove(encodedResource); if (currentResources.isEmpty()) { this.resourcesCurrentlyBeingLoaded.remove(); } } } 复制代码
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); int countBefore = getRegistry().getBeanDefinitionCount(); documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); return getRegistry().getBeanDefinitionCount() - countBefore; } 复制代码
实际上所谓的注册,就是把beanName和beanDefinition对象作为键值对放到BeanFactory对象的beanDefinitionMap。
prepareBeanFactory :准备BeanFactory,设置一些参数,比如后置处理器,
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { // //设置类加载器 // Tell the internal bean factory to use the context's class loader etc. beanFactory.setBeanClassLoader(getClassLoader()); //设置表达式解析器,用来解析BeanDefiniton中的带有表达式的值,spring3增加了表达式语言的支持,默认可以使用#{bean.xxx}的形式来调用相关属性值。 beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader())); // 增加了一个默认的propertyEditor,这个主要是对bean的属性等设置管理的一个工具 beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment())); // 配置后置处理器,主要的作用就是在spring实例化bean的前后做一些操作。 // 添加了一个处理aware相关接口的beanPostProcessor扩展,实现了 Aware 接口的 beans 在初始化的时候,这个 processor 负责回调, // 主要是使用beanPostProcessor的postProcessBeforeInitialization()前置处理方法实现aware相关接口的功能, // aware接口是用来给bean注入一些资源的接口, // 回调 ApplicationContextAware、EnvironmentAware、ResourceLoaderAware。 beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); //忽略自动装配的类,这些类都不能使用@Resource或者@Autowired自动装配获取对象 // 如果某个 bean 依赖于以下几个接口的实现类,在自动装配的时候忽略它们, Spring 会通过其他方式来处理这些依赖。 beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class); beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class); beanFactory.ignoreDependencyInterface(MessageSourceAware.class); beanFactory.ignoreDependencyInterface(ApplicationContextAware.class); beanFactory.ignoreDependencyInterface(EnvironmentAware.class); //注册可解析的自动装配类的特殊规则,如果是BeanFactory类型,则注入beanFactory对象,如果是ResourceLoader、ApplicationEventPublisher、ApplicationContext类型则注入当前对象(applicationContext对象)。 // BeanFactory interface not registered as resolvable type in a plain factory. // MessageSource registered (and found for autowiring) as a bean. beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory); beanFactory.registerResolvableDependency(ResourceLoader.class, this); beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this); beanFactory.registerResolvableDependency(ApplicationContext.class, this); // 这里涉及到特殊的 bean,名为:loadTimeWeaver。 // 如果定义了则添加loadTimeWeaver功能的beanPostProcessor扩展,并且创建一个临时的classLoader来让其处理真正的bean。 // spring的loadTimeWeaver主要是通过 instrumentation 的动态字节码增强在装载期注入依赖。 // tips: ltw 是 AspectJ 的概念,指的是在运行期进行织入,这个和 Spring AOP 不一样, // 感兴趣的读者请参考关于 AspectJ 的另一篇文章 https://www.javadoop.com/post/aspectj 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())); } // Register default environment beans. if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment()); } /** * 这部分首先判断是否定义了名为systemProperties的bean,如果没有则加载系统获取当前系统属性System.getProperties()并注册为一个单例bean。假如有AccessControlException权限异常则创建一个ReadOnlySystemAttributesMap对象,可以看到创建时重写了getSystemAttribute()方法,查看ReadOnlySystemAttributesMap的代码可以得知在调用get方法的时候会去调用这个方法来获取key对应的对象,当获取依旧有权限异常AccessControlException的时候则返回null。 */ if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties()); } // 同上,此处是获得 系统环境变量 if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment()); } } 复制代码
在装配完成配置后执行这些后处理器,这里涉及到一些接口。 我们在开发时可以实现这些接口扩展功能,例如:InstantiationAwareBeanPostProcessor包含两个方法。一个是在实例化前调用,一个在实例化后,初始化前调用,可以用来做特殊作用,例如代理等等 DestructionAwareBeanPostProcessor在销毁前调用
MessageSource/事件监听器,初始化国际化信息资源
abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory 类
protected <T> T doGetBean( final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException { /* 1、转换beanName(别名转换) 平时开发中传入的参数name可能只是别名,也可能是FactoryBean,所以需要进行解析转换: (1)消除修饰符,比如name="&test",会去除&使name="test"; (2)解决spring中alias标签的别名问题 */ final String beanName = transformedBeanName(name); Object bean; //2、尝试从缓存(DefaultSingletonBeanRegistry$singletonFactories)中加载实例,如果获取不到就从singletonFactories中加载 // Eagerly check singleton cache for manually registered singletons. Object sharedInstance = getSingleton(beanName); //如果缓存中存在对应的bean if (sharedInstance != null && args == null) { if (logger.isDebugEnabled()) { if (isSingletonCurrentlyInCreation(beanName)) { logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference"); } else { logger.debug("Returning cached instance of singleton bean '" + beanName + "'"); } } //3、缓存渠道的bean的实例化。从缓存中获取的bean是原始状态的bean,需要在这里对bean进行bean实例化。 // 此时会进行 合并RootBeanDefinition、BeanPostProcessor进行实例前置处理、实例化、实例后置处理。 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { // 如果缓存中没有对应bean //4、循环依赖检查。 (构造器的循环依赖)循环依赖存在,则报错。 // @see https://blog.csdn.net/qq_36381855/article/details/79752689 // Fail if we're already creating this bean instance: // We're assumably within a circular reference. if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } // 5、如果缓存中没有数据,就会转到父类工厂去加载 //获取父工厂 // Check if bean definition exists in this factory. BeanFactory parentBeanFactory = getParentBeanFactory(); /* !containsBeanDefinition(beanName)就是检测如果当前加载的xml配置文件中不包含beanName所对应的 配置,就只能到parentBeanFacotory去尝试加载bean。 */ if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { // Not found -> check parent. String nameToLookup = originalBeanName(name); if (args != null) { // Delegation to parent with explicit args. return (T) parentBeanFactory.getBean(nameToLookup, args); } else { // No args -> delegate to standard getBean method. return parentBeanFactory.getBean(nameToLookup, requiredType); } } if (!typeCheckOnly) { markBeanAsCreated(beanName); } //6、存储XML配置文件的GernericBeanDefinition转换成RootBeanDefinition,即为合并父类定义。 /* XML配置文件中读取到的bean信息是存储在GernericBeanDefinition中的,但Bean的后续处理是针 对于RootBeanDefinition的,所以需要转换后才能进行后续操作。 */ try { final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); // Guarantee initialization of beans that the current bean depends on. //7、初始化依赖的bean String[] dependsOn = mbd.getDependsOn(); //bean中可能依赖了其他bean属性,在初始化bean之前会先初始化这个bean所依赖的bean属性。 if (dependsOn != null) { for (String dependsOnBean : dependsOn) { if (isDependent(beanName, dependsOnBean)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'"); } registerDependentBean(dependsOnBean, beanName); getBean(dependsOnBean); } } //8、创建bean // Create bean instance. if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() { @Override public Object getObject() throws BeansException { 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. destroySingleton(beanName); throw ex; } } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } else if (mbd.isPrototype()) { // It's a prototype -> create a new instance. Object prototypeInstance = null; try { beforePrototypeCreation(beanName); prototypeInstance = createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } else { String scopeName = mbd.getScope(); final Scope scope = this.scopes.get(scopeName); if (scope == null) { throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'"); } try { Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() { @Override public Object getObject() throws BeansException { beforePrototypeCreation(beanName); try { return createBean(beanName, mbd, args); } finally { 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; } } // Check if required type matches the type of the actual bean instance. if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) { try { return getTypeConverter().convertIfNecessary(bean, requiredType); } catch (TypeMismatchException ex) { if (logger.isDebugEnabled()) { logger.debug("Failed to convert bean '" + name + "' to required type [" + ClassUtils.getQualifiedName(requiredType) + "]", ex); } throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } } return (T) bean; } 复制代码