spring 详解笔记
各变量说明
对象名
类 型
作 用
归属类
aliasMap
Map<String, String>
存储Bean名称->Bean别名映射关系
SimpleAliasRegistry
singletonObjects
Map<String, Object>
存储单例Bean名称->单例Bean实现映射关系
DefaultSingletonBeanRegistry
singletonFactories
Map<String, ObjectFactory>
存储Bean名称->ObjectFactory实现映射关系
DefaultSingletonBeanRegistry
earlySingletonObjects
Map<String, Object>
存储Bean名称->预加载Bean实现映射关系
DefaultSingletonBeanRegistry
registeredSingletons
Set
存储注册过的Bean名
DefaultSingletonBeanRegistry
singletonsCurrentlyInCreation
Set
存储当前正在创建的Bean名
DefaultSingletonBeanRegistry
disposableBeans
Map<String, Object>
存储Bean名称->Disposable接口实现Bean实现映射关系
DefaultSingletonBeanRegistry
factoryBeanObjectCache
Map<String, Object>
存储Bean名称->FactoryBean接口Bean实现映射关系
FactoryBeanRegistrySupport
propertyEditorRegistrars
Set
存储PropertyEditorRegistrar接口实现集合
AbstractBeanFactory
embeddedValueResolvers
List
存储StringValueResolver(字符串解析器)接口实现列表
AbstractBeanFactory
beanPostProcessors
List
存储 BeanPostProcessor接口实现列表
AbstractBeanFactory
mergedBeanDefinitions
Map<String, RootBeanDefinition>
存储Bean名称->合并过的根Bean定义映射关系
AbstractBeanFactory
alreadyCreated
Set
存储至少被创建过一次的Bean名集合
AbstractBeanFactory
ignoredDependencyInterfaces
Set
存储不自动装配的接口Class对象集合 AbstractAutowireCapableBeanFactory
resolvableDependencies
Map<Class, Object>
存储修正过的依赖映射关系
DefaultListableBeanFactory
beanDefinitionMap
Map<String, BeanDefinition>
存储Bean名称–>Bean定义映射关系
DefaultListableBeanFactory
beanDefinitionNames
List
存储Bean定义名称列表
DefaultListableBeanFactory
Ioc BeanFactory&&Application
BeanFactory
实现了容器的最基本功能getBean
AutowireCapableBeanFactory
实现自动装配能力,为bean注入属性autowireBeanProperties
,bean的实例化initializeBean
,各类装配autowire
HierarchicalBeanFactory
继承了BeanFactory
的基本接口之后
增加了getParentBeanFactory()
的接口功能,使BeanFactory具备双亲IOC容器的管理功能
ConfigurableBeanFactory
接口中定义了一些对BeanFactory的配置功能
setParentBeanFactory()
设置双亲IOC容器
addBeanPostProcessor()
配置Bean后置处理器
ListableBeanFactory
细化了很多BeanFactory的接口功能
getBeanDefinitionNames()
接口方法
AbstractApplicationContext 整个Spring的声明周期类
函数名
功能
prepareRefresh
容器预先准备,记录容器启动时间和标记
obtainFreshBeanFactory
创建Bean工厂,有则销毁无则创建,实现了beanDefinition
装载
prepareBeanFactory
配置bean工厂标准上下文,如类装载器,PostProcesser等
postProcessorBeanFactory
模板方法,提供后期准备
invokeBeanFactoryPostProcessor
传进来的是beanFactory,可以这个bean去获得各个beanDefinition并修改
registerBeanPostProcessors
注册BeanPostProcessor
initMessageSource
初始化MessageResource
initApplicationEventMulticaster
初始化上下文事件广播
onRefresh
最重要的方法,AnnotationConfigEmbeddedWebApplication是用来创建Servlet容器
registerListeners
注册监听器,实现ApplicationListener的监听器
finishBeanFactoryInitialization
preInstantiateSingletons让单例提前实例化
finishRefresh
LifecycleProcessor().onRefresh() 实现LifecycleProcessor的进行refresh并且发出event
obtainFreshBeanFactory --> refreshBeanFactory
负责BeanDefinition
资源的定位、读入和注册过程
prepareBeanFactory
ignoreDependencyInterface:设置了几个忽略自动装配的接口,主要功能是Bean如果是这些接口的实现类,则不会被自动装配,ApplicationContextAwareProcessor
registerResolvableDependency:设置了几个忽略自动装配的接口,意思是修正依赖,这里是一些自动装配的特殊规则,比如是BeanFactory接口的实现类,则修正为当前BeanFactory
refresh()方法解析 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 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 { resetCommonCaches(); } } }
AbstractBeanFactory
有关循环依赖A中有依赖B,B中有依赖A的Spring解决方案
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 三级缓存分别指: singletonFactories : 单例对象工厂的cache earlySingletonObjects :提前暴光的单例对象的Cache singletonObjects:单例对象的cache protected Object getSingleton(String beanName, boolean allowEarlyReference) { Object singletonObject = this.singletonObjects.get(beanName); 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(); this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } return (singletonObject != NULL_OBJECT ? singletonObject : null); } 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); } } }
A的某个field或者setter依赖了B的实例对象,同时B的某个field或者setter依赖了A的实例对象”这种循环依赖的情况。A首先完成了初始化的第一步,并且将自己提前曝光到singletonFactories中,此时进行初始化的第二步,发现自己依赖对象B,此时就尝试去get(B),发现B还没有被create,所以走create流程,B在初始化第一步的时候发现自己依赖了对象A,于是尝试get(A),尝试一级缓存singletonObjects(肯定没有,因为A还没初始化完全),尝试二级缓存earlySingletonObjects(也没有),尝试三级缓存singletonFactories,由于A通过ObjectFactory将自己提前曝光了,所以B能够通过ObjectFactory.getObject拿到A对象(虽然A还没有初始化完全,但是总比没有好呀),B拿到A对象后顺利完成了初始化阶段1、2、3,完全初始化之后将自己放入到一级缓存singletonObjects中。此时返回A中,A此时能拿到B的对象顺利完成自己的初始化阶段2、3,最终A也完成了初始化,进去了一级缓存singletonObjects中,而且更加幸运的是,由于B拿到了A的对象引用,所以B现在hold住的A对象完成了初始化。
doGetBean
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 protected <T> T doGetBean ( final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException { final String beanName = transformedBeanName(name); Object bean; Object sharedInstance = getSingleton(beanName); 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 + "'" ); } } bean = getObjectForBeanInstance(sharedInstance, name, beanName, null ); } else { if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { String nameToLookup = originalBeanName(name); if (args != null ) { return (T) parentBeanFactory.getBean(nameToLookup, args); } else { return parentBeanFactory.getBean(nameToLookup, requiredType); } } if (!typeCheckOnly) { markBeanAsCreated(beanName); } try { final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); String[] dependsOn = mbd.getDependsOn(); 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); } } if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() { @Override public Object getObject () throws BeansException { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { destroySingleton(beanName); throw ex; } } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } else if (mbd.isPrototype()) { 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; } } 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; }
createBean 1 2 3 4 5 6 7 8 9 10 11 12 13 先实例化createBeanInstance 后检测是否需要earlySingletonExposure,需要则加入addSingletonFactory 再进行设置对象属性populateBean(后期对BeanWrapper进行applyPropertyValues) 接下来进入initializeBean initializeBean主要进行四步骤 - invokeAwareMethods(BeanNameAware,BeanClassLoaderAware,BeanFactoryAware进行各种资源set) - BeanPostProcessor#postProcessBeforeInitialization - InitializingBean#afterPropertiesSet(如果当前的bean实现此接口就执行) - invokeInitMethods#invokeCustomInitMethod(如果有自定义init-method,则进行init-method实例化) - BeanPostProcessor#postProcessAfterInitialization 至此结束
createBeanInstance
: 创建bean
的时候将会选取实例化策略SimpleInstantiationStrategy
,CglibSubclassingInstantiationStrategy
通过BeanUtils
,利用JVM的反射功能
利用CGLIB
去生成代理
如果有使用到lookup-method
或replace-method
,进入到instantiateBean方法
可以看到如果有方法覆盖(MethodOverride
)将调用cglib的instantiateWithMethodInjection
BeanDefinitionReader XmlBeanDefinitionReader 1 2 3 4 5 6 7 AbstractWebApplicationContext#invokeBeanFactoryPostProcessors ---> PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors //invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry); //调用BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry ConfigurationClassPostProcessor#processConfigBeanDefinitions //this.reader.loadBeanDefinitions(configClasses); 由此引入XmlBeanDefinitionReader
AnnotatedBeanDefinitionReader 1 SpringApplication#prepareContext ---> SpringApplication#load
生命周期
扩展 InitialingBean
InitialingBean是一个接口,提供了一个唯一的方法afterPropertiesSet()。
在Bean属性都设置完毕后调用afterPropertiesSet()方法做一些初始化的工作
1 afterPropertiesSet方法在set属性之后执行
DisposableBean
DisposableBean也是一个接口,提供了一个唯一的方法destory()。
在Bean生命周期结束前调用destory()方法做一些收尾工作
InitializingBean接口、Disposable接口底层进行直接方法调用 init-method、destory-method底层使用反射 前者和Spring耦合程度更高但效率高 后者解除了和Spring之间的耦合但是效率低
BeanNameAware
实现BeanNameAware接口的Bean,在Bean加载的过程中可以获取到该Bean的id
1 2 3 4 5 public void setBeanName (String beanName) { System.out.println("Enter AwareBean.setBeanName(), beanName = " + beanName + "\n" ); this .beanName = beanName; }
ApplicationContextAware
Bean加载的过程中可以获取到Spring的ApplicationContext
从ApplicationContext中可以获取包括任意的Bean在内的大量Spring容器内容和信息
1 2 3 4 5 public void setApplicationContext (ApplicationContext applicationContext) throws BeansException { System.out.println("Enter AwareBean.setApplicationContext(), applicationContext = " + applicationContext + "\n" ); this .applicationContext = applicationContext; }
BeanFactoryAware
Bean加载的过程中可以获取到加载该Bean的BeanFactory
1 2 3 4 5 public void setBeanFactory (BeanFactory beanFactory) throws BeansException { System.out.println("Enter AwareBean.setBeanFactory(), beanfactory = " + beanFactory + "\n" ); this .beanFactory = beanFactory; }
FactoryBean
FactoryBean,开发者可以个性化地定制自己想要实例化出来的Bean,方法就是实现FactoryBean接口。
getObject()方法是最重要的,控制Bean的实例化过程
getObjectType()方法获取接口返回的实例的class
isSingleton()方法获取该Bean是否为一个单例的Bean
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public class AnimalFactoryBean implements FactoryBean <Animal > { private String animal; public Animal getObject () throws Exception { if ("Monkey" .equals(animal)) { return new Monkey(); } else if ("Tiger" .equals(animal)) { return new Tiger(); } else { return null ; } } public Class<?> getObjectType(){ return Animal.class; } public boolean isSingleton () { return true ; } public void setAnimal (String animal) { this .animal = animal; } }
BeanPostProcess
不要返回null,否则getBean的时候拿不到对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class PostProcessorBean implements BeanPostProcessor { public Object postProcessAfterInitialization (Object bean, String beanName) throws BeansException { System.out.println("Enter ProcessorBean.postProcessAfterInitialization()\n" ); return bean; } public Object postProcessBeforeInitialization (Object bean, String beanName) throws BeansException { System.out.println("Enter ProcessorBean.postProcessBeforeInitialization()" ); return bean; } }
BeanFactoryPostProcessor PostProcessor之后的BeanFactoryPostProcessor
BeanFactoryPostProcessor的执行优先级高于BeanPostProcessor
BeanFactoryPostProcessor的postProcessBeanFactory()方法只会执行一次
InstantiationAwareBeanPostProcessor
实例化:实例化的过程是一个创建Bean的过程,即调用Bean的构造函数,单例的Bean放入单例池中
初始化:初始化的过程是一个赋值的过程,即调用Bean的setter,设置Bean的属性
BeanDefinitionRegistryPostProcessor 这个接口继承了BeanFactoryPostProcessor
. 从名字上来看, 这个接口是BeanDefinitionRegistry
的后处理器
我们先介绍下BeanDefinitionRegistry. BeanDefinitionRegistry是用来注册BeanDefinition的. BeanDefinition就是Bean的配置元数据或Bean的描述信息, 比如Bean的属性值, 构造方法的参数值等. 上面的BeanFactory的BeanDefinition也是由它注册的.
BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的扩展, 允许在BeanFactoryPostProcessor被调用之前对BeanDefinition做一些操作, 尤其是它可以注册BeanFactoryPostProcessor的BeanDefinition. 它提供了一个方法postProcessBeanDefinitionRegistry(), 这个方法被调用的时候, 所有的BeanDefinition已经被加载了, 但是所有的Bean还没被创建.
注意:
所有的Bean生成都有个顺序: 定义 –> 创建 –> 初始化. BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法在Bean被定义但还没被创建的时候执行. BeanFactoryPostProcessor的postProcessBeanFactory方法在Bean被创建但还没被初始化的时候执行
案例 Mybatis的MapperScannerConfigurer
ImportBeanDefinitionRegistrar
动态注册bean Spring官方在动态注册bean时,大部分套路其实是使用ImportBeanDefinitionRegistrar接口。
所有实现了该接口的类的都会被ConfigurationClassPostProcessor处理,ConfigurationClassPostProcessor实现了BeanFactoryPostProcessor接口 所以ImportBeanDefinitionRegistrar中动态注册的bean是优先与依赖其的bean初始化的,也能被aop、validator等机制处理。
案例 Apollo阿波罗配置框架ApolloConfigRegistrar
Mybatis的@MapperScan
中Import了ImportBeanDefinitionRegistrar
工具类 内置的resouce类型 1 2 3 4 5 6 7 8 UrlResource ClassPathResource FileSystemResource ServletContextResource InputStreamResource ByteArrayResource EncodedResource org.springframework.util.xml.ResourceUtils
常用工具 1 2 3 4 5 6 org.springframework.core.annotation.AnnotationUtils 处理注解 org.springframework.core.io.support.PathMatchingResourcePatternResolver 用 于处理 ant 匹配风格(com*.jsp),找出所有的资源, 结合上面的resource的概念一起使用,对于遍历文件很有用. 具体请详细查看javadoc org.springframework.core.io.support.PropertiesLoaderUtils 加载Properties资源工具类,和Resource结合 org.springframework.core.BridgeMethodResolver 桥接方法分析器. 关于桥接方法请参考: http: org.springframework.core.GenericTypeResolver 范型分析器, 在用于对范型方法, 参数分析. org.springframework.core.NestedExceptionUtils
xml工具 org.springframework.util.xml.AbstractStaxContentHandler org.springframework.util.xml.AbstractStaxXMLReader org.springframework.util.xml.AbstractXMLReader org.springframework.util.xml.AbstractXMLStreamReader org.springframework.util.xml.DomUtils org.springframework.util.xml.SimpleNamespaceContext org.springframework.util.xml.SimpleSaxErrorHandler org.springframework.util.xml.SimpleTransformErrorListener org.springframework.util.xml.StaxUtils org.springframework.util.xml.TransformerUtils
其它工具集 org.springframework.util.xml.AntPathMatcher ant风格的处理 org.springframework.util.xml.AntPathStringMatcher org.springframework.util.xml.Assert 断言,在我们的参数判断时应该经常用 org.springframework.util.xml.CachingMapDecorator org.springframework.util.xml.ClassUtils 用于Class的处理 org.springframework.util.xml.CollectionUtils 用于处理集合的工具 org.springframework.util.xml.CommonsLogWriter org.springframework.util.xml.CompositeIterator org.springframework.util.xml.ConcurrencyThrottleSupport org.springframework.util.xml.CustomizableThreadCreator org.springframework.util.xml.DefaultPropertiesPersister org.springframework.util.xml.DigestUtils 摘要处理, 这里有用于md5处理信息的 org.springframework.util.xml.FileCopyUtils 文件的拷贝处理, 结合Resource的概念一起来处理, 真的是很方便 org.springframework.util.xml.FileSystemUtils org.springframework.util.xml.LinkedCaseInsensitiveMap key值不区分大小写的LinkedMap org.springframework.util.xml.LinkedMultiValueMap 一个key可以存放多个值的LinkedMap org.springframework.util.xml.Log4jConfigurer 一个log4j的启动加载指定配制文件的工具类 org.springframework.util.xml.NumberUtils 处理数字的工具类, 有parseNumber 可以把字符串处理成我们指定的数字格式, 还支持format格式, convertNumberToTargetClass 可以实现Number类型的转化. org.springframework.util.xml.ObjectUtils 有很多处理null object的方法. 如nullSafeHashCode, nullSafeEquals, isArray, containsElement, addObjectToArray, 等有用的方法 org.springframework.util.xml.PatternMatchUtils spring里用于处理简单的匹配. org.springframework.util.xml.PropertyPlaceholderHelper 用于处理占位符的替换 org.springframework.util.xml.ReflectionUtils 反映常用工具方法. 有 findField, setField, getField, findMethod, invokeMethod等有用的方法 org.springframework.util.xml.SerializationUtils 用于java的序列化与反序列化. serialize与deserialize方法 org.springframework.util.xml.StopWatch 一个很好的用于记录执行时间的工具类, 且可以用于任务分阶段的测试时间. 最后支持一个很好看的打印格式. 这个类应该经常用 org.springframework.util.xml.StringUtils org.springframework.util.xml.SystemPropertyUtils org.springframework.util.xml.TypeUtils 用于类型相容的判断. isAssignable org.springframework.util.xml.WeakReferenceMonitor 弱引用的监控
web相关 org.springframework.web.util.CookieGenerator org.springframework.web.util.HtmlCharacterEntityDecoder org.springframework.web.util.HtmlCharacterEntityReferences org.springframework.web.util.HtmlUtils org.springframework.web.util.HttpUrlTemplate //这个类用于用字符串模板构建url, 它会自动处理url里的汉字及其它相关的编码. 在读取别人提供的url资源时, 应该经常用 org.springframework.web.util.JavaScriptUtils org.springframework.web.util.Log4jConfigListener //用listener的方式来配制log4j在web环境下的初始化 org.springframework.web.util.UriTemplate org.springframework.web.util.UriUtils 处理uri里特殊字符的编码 org.springframework.web.util.WebUtils
Aop 一个正常的提前实例化单例实例
1 2 3 4 5 sequenceDiagram AbstractApplicationContext->>AbstractApplicationContext:refresh AbstractApplicationContext->>AbstractApplicationContext:finishBeanFactoryInitialization AbstractApplicationContext->>DefaultListableBeanFactory:preInstantiateSingletons DefaultListableBeanFactory->>DefaultListableBeanFactory:getBean.......
AbstractAutoProxyCreator
因继承SmartInstantiationAwareBeanPostProcessor
,重写了postProcessAfterInitialization
,让每个bean实例化后进入这里判断
AbstractAutoProxyCreator 1 2 3 4 5 6 7 8 9 10 @Override public Object postProcessAfterInitialization (Object bean, String beanName) throws BeansException { if (bean != null ) { Object cacheKey = getCacheKey(bean.getClass(), beanName); if (!this .earlyProxyReferences.contains(cacheKey)) { return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; }
wrapIfNecessary 判断是否要初始化1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 protected Object wrapIfNecessary (Object bean, String beanName, Object cacheKey) { if (beanName != null && this .targetSourcedBeans.contains(beanName)) { return bean; } if (Boolean.FALSE.equals(this .advisedBeans.get(cacheKey))) { return bean; } if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this .advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null ); if (specificInterceptors != DO_NOT_PROXY) { this .advisedBeans.put(cacheKey, Boolean.TRUE); 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; }
createProxy 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 protected Object createProxy ( Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) { if (this .beanFactory instanceof ConfigurableListableBeanFactory) { AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this .beanFactory, beanName, beanClass); } ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.copyFrom(this ); if (!proxyFactory.isProxyTargetClass()) { if (shouldProxyTargetClass(beanClass, beanName)) { proxyFactory.setProxyTargetClass(true ); } else { evaluateProxyInterfaces(beanClass, proxyFactory); } } Advisor[] advisors = buildAdvisors(beanName, specificInterceptors); for (Advisor advisor : advisors) { proxyFactory.addAdvisor(advisor); } proxyFactory.setTargetSource(targetSource); customizeProxyFactory(proxyFactory); proxyFactory.setFrozen(this .freezeProxy); if (advisorsPreFiltered()) { proxyFactory.setPreFiltered(true ); } return proxyFactory.getProxy(getProxyClassLoader()); }
proxyFactory.getProxy 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public AopProxy createAopProxy (AdvisedSupport config) throws AopConfigException { if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { Class<?> targetClass = config.getTargetClass(); if (targetClass == null ) { throw new AopConfigException("TargetSource cannot determine target class: " + "Either an interface or a target is required for proxy creation." ); } if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); } return new ObjenesisCglibAopProxy(config); } else { return new JdkDynamicAopProxy(config); } }
JdkDynamicAopProxy 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 @Override public Object getProxy (ClassLoader classLoader) { if (logger.isDebugEnabled()) { logger.debug("Creating JDK dynamic proxy: target source is " + this .advised.getTargetSource()); } Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this .advised); findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this ); } @Override public Object invoke (Object proxy, Method method, Object[] args) throws Throwable { MethodInvocation invocation; Object oldProxy = null ; boolean setProxyContext = false ; TargetSource targetSource = this .advised.targetSource; Class<?> targetClass = null ; Object target = null ; try { if (!this .equalsDefined && AopUtils.isEqualsMethod(method)) { return equals(args[0 ]); } if (!this .hashCodeDefined && AopUtils.isHashCodeMethod(method)) { return hashCode(); } if (!this .advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) { return AopUtils.invokeJoinpointUsingReflection(this .advised, method, args); } Object retVal; if (this .advised.exposeProxy) { oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true ; } target = targetSource.getTarget(); if (target != null ) { targetClass = target.getClass(); } List<Object> chain = this .advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); if (chain.isEmpty()) { Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse); } else { invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); retVal = invocation.proceed(); } Class<?> returnType = method.getReturnType(); if (retVal != null && retVal == target && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { retVal = proxy; } else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) { throw new AopInvocationException( "Null return value from advice does not match primitive return type for: " + method); } return retVal; } finally { if (target != null && !targetSource.isStatic()) { targetSource.releaseTarget(target); } if (setProxyContext) { AopContext.setCurrentProxy(oldProxy); } } }
ObjenesisCglibAopProxy 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 public Object getProxy (ClassLoader classLoader) { if (logger.isDebugEnabled()) { logger.debug("Creating CGLIB proxy: target source is " + this .advised.getTargetSource()); } try { Class<?> rootClass = this .advised.getTargetClass(); Assert.state(rootClass != null , "Target class must be available for creating a CGLIB proxy" ); Class<?> proxySuperClass = rootClass; if (ClassUtils.isCglibProxyClass(rootClass)) { proxySuperClass = rootClass.getSuperclass(); Class<?>[] additionalInterfaces = rootClass.getInterfaces(); for (Class<?> additionalInterface : additionalInterfaces) { this .advised.addInterface(additionalInterface); } } validateClassIfNecessary(proxySuperClass, classLoader); Enhancer enhancer = createEnhancer(); if (classLoader != null ) { enhancer.setClassLoader(classLoader); if (classLoader instanceof SmartClassLoader && ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) { enhancer.setUseCache(false ); } } enhancer.setSuperclass(proxySuperClass); enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this .advised)); enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE); enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader)); Callback[] callbacks = getCallbacks(rootClass); Class<?>[] types = new Class<?>[callbacks.length]; for (int x = 0 ; x < types.length; x++) { types[x] = callbacks[x].getClass(); } enhancer.setCallbackFilter(new ProxyCallbackFilter( this .advised.getConfigurationOnlyCopy(), this .fixedInterceptorMap, this .fixedInterceptorOffset)); enhancer.setCallbackTypes(types); return createProxyClassAndInstance(enhancer, callbacks); } catch (CodeGenerationException ex) { throw new AopConfigException("Could not generate CGLIB subclass of class [" + this .advised.getTargetClass() + "]: " + "Common causes of this problem include using a final class or a non-visible class" , ex); } catch (IllegalArgumentException ex) { throw new AopConfigException("Could not generate CGLIB subclass of class [" + this .advised.getTargetClass() + "]: " + "Common causes of this problem include using a final class or a non-visible class" , ex); } catch (Exception ex) { throw new AopConfigException("Unexpected AOP exception" , ex); } } protected Object createProxyClassAndInstance (Enhancer enhancer, Callback[] callbacks) { Class<?> proxyClass = enhancer.createClass(); Object proxyInstance = null ; if (objenesis.isWorthTrying()) { try { proxyInstance = objenesis.newInstance(proxyClass, enhancer.getUseCache()); } catch (Throwable ex) { logger.debug("Unable to instantiate proxy using Objenesis, " + "falling back to regular proxy construction" , ex); } } if (proxyInstance == null ) { try { proxyInstance = (this .constructorArgs != null ? proxyClass.getConstructor(this .constructorArgTypes).newInstance(this .constructorArgs) : proxyClass.newInstance()); } catch (Throwable ex) { throw new AopConfigException("Unable to instantiate proxy using Objenesis, " + "and regular proxy instantiation via default constructor fails as well" , ex); } } ((Factory) proxyInstance).setCallbacks(callbacks); return proxyInstance; }
MVC
根据http请求选择合适的controller是MVC中一项十分关键的功能
SimpleUrlHandlerMapping //使用定义在spring应用上下文的属性集合,将控制器映射到url上
RequestMappingHandlerMapping //使用@RequestMapping注解以前叫DefaultAnnotationHandlerMapping
ControllerClassNameHandlerMapping //使用控制器的类名作为URL基础将控制器映射到URL上
ControllerBeanNamHandlerMapping //根据控制器Bean的名字作为URL基础将控制器映射到URL上
获取相关的handler,HandlerExecutionChain(执行链)
DispatcherServlet 初始化体系 EmbeddedWebApplicationContext中selfInitialize 当TomcatEmbeddedServletContainer初始化到最后一层Wrapper后调用selfInitialize添加servlet,filter 后期各类pipeline的vavle一直从server->service->engine->host->context->wrapper->filterChain->servlet 其他HandlerMapping如:SimpleUrl,RequestMapping等会等到AbstractApplicationContext#finishBeanFactoryInitialization实例化 执行各类HandlerMapping#afterPropertiesSet—>initHandlerMethods为每个method添加到相关的handlerMapping
selfInitialize 初始化方法,wrapper最后会进行这个selfInitialize
1 2 3 4 5 6 for (ServletContextInitializer beans : getServletContextInitializerBeans()) { beans.onStartup(servletContext); }
由此bean的onStartUp展开了对dispatcher的加载
ServletRegistrationBean 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 ServletRegistrationBean#onStartup public void onStartup (ServletContext servletContext) throws ServletException { String name = getServletName(); ..... Dynamic added = servletContext.addServlet(name, this .servlet); configure(added); } private ServletRegistration.Dynamic addServlet (String servletName, String servletClass, Servlet servlet) throws IllegalStateException { Wrapper wrapper = (Wrapper) context.findChild(servletName); if (wrapper == null ) { wrapper = context.createWrapper(); wrapper.setName(servletName); context.addChild(wrapper); } else { if (wrapper.getName() != null && wrapper.getServletClass() != null ) { if (wrapper.isOverridable()) { wrapper.setOverridable(false ); } else { return null ; } } } if (servlet == null ) { wrapper.setServletClass(servletClass); } else { wrapper.setServletClass(servlet.getClass().getName()); wrapper.setServlet(servlet); } return context.dynamicServletAdded(wrapper); }
FilterRegistrationBean 1 2 3 4 5 6 7 8 9 10 AbstractFilterRegistrationBean#onStartup public void onStartup (ServletContext servletContext) throws ServletException { Filter filter = getFilter(); String name = getOrDeduceName(filter); FilterRegistration.Dynamic added = servletContext.addFilter(name, filter); configure(added); }
建立体系 RequestMappingHandlerMapping
RequestMappingHandlerMapping
继承了InitializingBean
实现了afterPropertiesSet
往上一级 AbstractHandlerMethodMapping super.afterPropertiesSet(); 执行initHandlerMethods();
->detectHandlerMethods
->getMappingForMethod
->registerHandlerMethod
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 protected void initHandlerMethods () { if (logger.isDebugEnabled()) { logger.debug("Looking for request mappings in application context: " + getApplicationContext()); } String[] beanNames = (this .detectHandlerMethodsInAncestorContexts ? BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) : getApplicationContext().getBeanNamesForType(Object.class)); for (String beanName : beanNames) { if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) { Class<?> beanType = null ; try { beanType = getApplicationContext().getType(beanName); } catch (Throwable ex) { if (logger.isDebugEnabled()) { logger.debug("Could not resolve target class for bean with name '" + beanName + "'" , ex); } } if (beanType != null && isHandler(beanType)) { detectHandlerMethods(beanName); } } } handlerMethodsInitialized(getHandlerMethods()); } protected void detectHandlerMethods (final Object handler) { Class<?> handlerType = (handler instanceof String ? getApplicationContext().getType((String) handler) : handler.getClass()); final Map<Method, T> mappings = new IdentityHashMap<Method, T>(); final Class<?> userType = ClassUtils.getUserClass(handlerType); Set<Method> methods = HandlerMethodSelector.selectMethods(userType, new MethodFilter() { @Override public boolean matches (Method method) { T mapping = getMappingForMethod(method, userType); if (mapping != null ) { mappings.put(method, mapping); return true ; } else { return false ; } } }); for (Method method : methods) { registerHandlerMethod(handler, method, mappings.get(method)); } } @Deprecated protected void registerHandlerMethod (Object handler, Method method, T mapping) { this .mappingRegistry.register(mapping, handler, method); } @Override protected RequestMappingInfo getMappingForMethod (Method method, Class<?> handlerType) { RequestMappingInfo info = createRequestMappingInfo(method); if (info != null ) { RequestMappingInfo typeInfo = createRequestMappingInfo(handlerType); if (typeInfo != null ) { info = typeInfo.combine(info); } } return info; } private RequestMappingInfo createRequestMappingInfo (AnnotatedElement element) { RequestMapping requestMapping = AnnotatedElementUtils.findMergedAnnotation(element, RequestMapping.class); RequestCondition<?> condition = (element instanceof Class<?> ? getCustomTypeCondition((Class<?>) element) : getCustomMethodCondition((Method) element)); return (requestMapping != null ? createRequestMappingInfo(requestMapping, condition) : null ); } private final Map<T, MappingRegistration<T>> registry = new HashMap<T, MappingRegistration<T>>(); private final Map<T, HandlerMethod> mappingLookup = new LinkedHashMap<T, HandlerMethod>(); private final MultiValueMap<String, T> urlLookup = new LinkedMultiValueMap<String, T>(); private final Map<String, List<HandlerMethod>> nameLookup = new ConcurrentHashMap<String, List<HandlerMethod>>(); private final Map<HandlerMethod, CorsConfiguration> corsLookup = new ConcurrentHashMap<HandlerMethod, CorsConfiguration>();public void register (T mapping, Object handler, Method method) { this .readWriteLock.writeLock().lock(); try { HandlerMethod handlerMethod = createHandlerMethod(handler, method); assertUniqueMethodMapping(handlerMethod, mapping); if (logger.isInfoEnabled()) { logger.info("Mapped \"" + mapping + "\" onto " + handlerMethod); } this .mappingLookup.put(mapping, handlerMethod); List<String> directUrls = getDirectUrls(mapping); for (String url : directUrls) { this .urlLookup.add(url, mapping); } String name = null ; if (getNamingStrategy() != null ) { name = getNamingStrategy().getName(handlerMethod, mapping); addMappingName(name, handlerMethod); } CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping); if (corsConfig != null ) { this .corsLookup.put(handlerMethod, corsConfig); } this .registry.put(mapping, new MappingRegistration<T>(mapping, handlerMethod, directUrls, name)); } finally { this .readWriteLock.writeLock().unlock(); } }
RequestMappingHandlerAdapter
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @Override public void afterPropertiesSet () { initControllerAdviceCache(); if (this .argumentResolvers == null ) { List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers(); this .argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers); } if (this .initBinderArgumentResolvers == null ) { List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers(); this .initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers); } if (this .returnValueHandlers == null ) { List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers(); this .returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers); } }
初始化各类argumentResolvers
初始化各类returnValueHandlers
忽略ViewName视图解析,Json数据返回
1 2 3 4 5 6 7 8 9 public void handleReturnValue (Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException { mavContainer.setRequestHandled(true ); ServletServerHttpRequest inputMessage = createInputMessage(webRequest); ServletServerHttpResponse outputMessage = createOutputMessage(webRequest); writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage); }
mavContainer.setRequestHandled(true);
设置true
writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
:会进行HttpMessageConverter#write
操作,直接将信息write出去
FastJsonHttpMessageConverter
是HttpMessageConverter
实现类
FastJsonHttpMessageConverter
是HttpMessageConverter
实现类
主体流程 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 DispatcherServlet --->doService--->doDispatcher() ---->mappedHandler = getHandler(request): ---->getHandlerAdapter(mappedHandler.getHandler()); ----->mappedHandler.applyPreHandle -----> ha.handle(processedRequest, response, mappedHandler.getHandler()); -----> handleInternal----> invokeHandlerMethod ------> invokeAndHandle -----> invokeForRequest -----> getMethodArgumentValues -----> doInvoke -------> returnValueHandlers -----> applyDefaultViewName(processedRequest, mv); ----->mappedHandler.applyPreHandle
获取处理器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 protected HandlerExecutionChain getHandler (HttpServletRequest request) throws Exception { for (HandlerMapping hm : this .handlerMappings) { if (logger.isTraceEnabled()) { logger.trace( "Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'" ); } HandlerExecutionChain handler = hm.getHandler(request); if (handler != null ) { return handler; } } return null ; } public final HandlerExecutionChain getHandler (HttpServletRequest request) throws Exception { Object handler = getHandlerInternal(request); if (handler == null ) { handler = getDefaultHandler(); } if (handler == null ) { return null ; } if (handler instanceof String) { String handlerName = (String) handler; handler = getApplicationContext().getBean(handlerName); } HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request); if (CorsUtils.isCorsRequest(request)) { CorsConfiguration globalConfig = this .corsConfigSource.getCorsConfiguration(request); CorsConfiguration handlerConfig = getCorsConfiguration(handler, request); CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig); executionChain = getCorsHandlerExecutionChain(request, executionChain, config); } return executionChain; }
执行流程
DispatcherServlet->>DispatcherServlet:doDispatch1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); | | | return handleInternal(request, response, (HandlerMethod) handler);| | | mav = invokeHandlerMethod(request, response, handlerMethod); | | | ######## ServletInvocableHandlerMethod ######## invocableMethod.invokeAndHandle(webRequest, mavContainer); | | | ######## InvocableHandlerMethod ######## Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs); | | | Object returnValue = doInvoke(args);
HandlerMapping:处理器映射器 作用:根据【请求】找到【处理器Handler】,但并不是简单的返回处理器,而是 将处理器和拦截器封装,形成一个处理器执行链(HandlerExecuteChain)。
HandlerExecuteChain包含以下:
interceptorList: 拦截器列表
handler: 执行器
DispatcherServlet 拿着执行链去寻找对应的处理器适配器(HandlerAdapter)
为什么要引入适配器? 因为处理器(Handler)有很多种,DispatcherServlet没办法统一管理,所以出现了适配器。
让适配器统一处理Handler,而DispatcherServlet统一处理适配器。
根据请求去找对应的handler
SpringBoot 自动配置
可以发现其最终实现了ImportSelector(选择器)和BeanClassLoaderAware(bean类加载器中间件)
重点关注一下AutoConfigurationImportSelector的selectImports方法
最终会根据@ConditionOnXXX各类条件
SpringApplication#run Boot启动函数 SpringApplication.run()
会启动一个AnnotationConfigEmbeddedWebApplicationContext
如果是SpringCloud项目会在environmentPrepared
函数作用下通过消息引导BootstrapApplicationListener
起AnnotationConfigApplicationContext
应用上下文,后期再启AnnotationConfigEmbeddedWebApplicationContext
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 public ConfigurableApplicationContext run (String... args) { StopWatch stopWatch = new StopWatch(); stopWatch.start(); ConfigurableApplicationContext context = null ; FailureAnalyzers analyzers = null ; configureHeadlessProperty(); SpringApplicationRunListeners listeners = getRunListeners(args); listeners.starting(); try { ApplicationArguments applicationArguments = new DefaultApplicationArguments( args); ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); Banner printedBanner = printBanner(environment); context = createApplicationContext(); analyzers = new FailureAnalyzers(context); prepareContext(context, environment, listeners, applicationArguments, printedBanner); refreshContext(context); afterRefresh(context, applicationArguments); listeners.finished(context, null ); stopWatch.stop(); if (this .logStartupInfo) { new StartupInfoLogger(this .mainApplicationClass) .logStarted(getApplicationLog(), stopWatch); } return context; } catch (Throwable ex) { handleRunFailure(context, listeners, analyzers, ex); throw new IllegalStateException(ex); } }
环境整理:prepareEnvironment
,主要设定webEnvironment
并执行预设环境的listener
创建上下文context:AnnotationConfigEmbeddedWebApplicationContext
刷新上下文context:refreshContext
结束刷新上下文context: 主要去调用一些接口实现ApplicationRunner
,CommandLineRunner
EmbeddedWebApplicationContext#onRefresh Spring上下文初始化+Servlet容器创造 AbstractApplicationContext#refresh
—>AnnotationEmbeddedWebApplication#onRefresh
—>EmbeddedWebApplicationContext##onRefresh
创建Servlet容器
1 2 3 4 5 6 7 8 9 10 11 @Override protected void onRefresh () { super .onRefresh(); try { createEmbeddedServletContainer(); } catch (Throwable ex) { throw new ApplicationContextException("Unable to start embedded container" , ex); } }
createEmbeddedServletContainer 创建内部Servlet容器
具体步骤
获取ServletContainer工厂类
从工厂类获取ServletContainer
ServletContainer获取的时候会实例化各个tomcat组件
getEmbeddedServletContainerFactory 获取Servlet容器工厂类 获取当前环境下的ServletContainer工厂类,默认为tomcatEmbeddedServletContainerFactory
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 protected EmbeddedServletContainerFactory getEmbeddedServletContainerFactory () { String[] beanNames = getBeanFactory() .getBeanNamesForType(EmbeddedServletContainerFactory.class); if (beanNames.length == 0 ) { throw new ApplicationContextException( "Unable to start EmbeddedWebApplicationContext due to missing " + "EmbeddedServletContainerFactory bean." ); } if (beanNames.length > 1 ) { throw new ApplicationContextException( "Unable to start EmbeddedWebApplicationContext due to multiple " + "EmbeddedServletContainerFactory beans : " + StringUtils.arrayToCommaDelimitedString(beanNames)); } return getBeanFactory().getBean(beanNames[0 ], EmbeddedServletContainerFactory.class); }
containerFactory.getEmbeddedServletContainer(getSelfInitializer()); 工厂类获取Servlet容器
丢初始化函数
tomcatEmbeddedServletContainerFactory
获取Servlet容器
getSelfInitializer
设置初始化函数,给以后各个Servlet进行OnStartUp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 private org.springframework.boot.web.servlet.ServletContextInitializer getSelfInitializer () { return new ServletContextInitializer() { @Override public void onStartup (ServletContext servletContext) throws ServletException { selfInitialize(servletContext); } }; } private void selfInitialize (ServletContext servletContext) throws ServletException { prepareEmbeddedWebApplicationContext(servletContext); ConfigurableListableBeanFactory beanFactory = getBeanFactory(); ExistingWebApplicationScopes existingScopes = new ExistingWebApplicationScopes( beanFactory); WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, getServletContext()); existingScopes.restore(); WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, getServletContext()); for (ServletContextInitializer beans : getServletContextInitializerBeans()) { beans.onStartup(servletContext); } }
getEmbeddedServletContainer Tomcat准备
实例化Tomcat,并设置setBaseDir(/var/folders/dd/hx_wl3v56_l_bb49fkyd759h0000gn/T/tomcat.7376236981941697730.8171)
实例化Connector,并设置protocolHandler
为org.apache.coyote.http11.Http11NioProtocol
Tomcat的Service关联相关的Connector:tomcat.getService().addConnector(connector);
tomcat.getService()
会实例化StandardServer
和StandardService
,并server.addService(service)
把service添加到server
从tomcat的server返回此Service并且添加一个Connector
configureEngine(tomcat.getEngine());
取Engine
并配置Engine
prepareContext(tomcat.getHost(), initializers);
预设上下文
从Engine
中取Host
如若存在则返回,否则实例化StandardHost
并添加到Engine
1 "localhost" -> "StandardEngine[Tomcat].StandardHost[localhost]"
整理TomcatEmbeddedContext
,添加各类listener
获取Tomcat的Servlet容器TomcatEmbeddedServletContainer
return getTomcatEmbeddedServletContainer(tomcat);
实例化TomcatEmbeddedServletContainer
并在构造函数初始化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 private void initialize () throws EmbeddedServletContainerException { synchronized (this .monitor) { try { addInstanceIdToEngineName(); try { removeServiceConnectors(); this .tomcat.start(); rethrowDeferredStartupExceptions(); Context context = findContext(); try { ContextBindings.bindClassLoader(context, getNamingToken(context), getClass().getClassLoader()); } catch (NamingException ex) { } startDaemonAwaitThread(); } catch (Exception ex) { containerCounter.decrementAndGet(); throw ex; } } catch (Exception ex) { throw new EmbeddedServletContainerException( "Unable to start embedded Tomcat" , ex); } } }
接下来相关Tomcat具体的步骤由Tomcat篇目解答
Jar-in-Jar Jar Launcher 1 2 3 4 5 6 maven打包之后,会生成两个jar文件: demo-0.0.1-SNAPSHOT.jar demo-0.0.1-SNAPSHOT.jar.original demo-0.0.1-SNAPSHOT.jar.original是默认的maven-jar-plugin生成的包。 demo-0.0.1-SNAPSHOT.jar是spring boot maven插件生成的jar包,里面包含了应用的依赖,以及spring boot相关的类称之为fat jar。
组织架构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 ├── BOOT-INF │ ├── classes │ │ ├── application.properties │ │ └── cn │ │ └── coderss │ │ └── reactive │ │ ├── WebApplication.class │ │ ├── bean │ │ │ ├── BO │ │ │ │ ├── IndexBO$IndexBOBuilder.class │ │ │ │ └── IndexBO.class │ │ │ ├── DO │ │ │ │ ├── UserDO$UserDOBuilder.class │ │ │ │ └── UserDO.class │ │ │ └── VO │ │ │ ├── IndexVO$IndexVOBuilder.class │ │ │ ├── IndexVO.class │ │ │ ├── UserVO$UserVOBuilder.class │ │ │ └── UserVO.class │ │ ├── config │ │ │ ├── WebMvcConfig.class │ │ │ └── handler │ │ │ ├── ObservableReturnValueHandler$ObservableAdapter.class │ │ │ └── ObservableReturnValueHandler.class │ │ ├── controller │ │ │ ├── IndexController.class │ │ │ ├── OtherController.class │ │ │ └── UserController.class │ │ ├── dao │ │ │ └── UserRepository.class │ │ └── service │ │ ├── IIndexService.class │ │ ├── IUserService.class │ │ └── impl │ │ ├── IndexServiceImpl.class │ │ └── UserServiceImpl.class │ └── lib │ ├── bson-3.6.4.jar │ .......... │ └── validation-api-2.0.1.Final.jar ├── META-INF │ ├── MANIFEST.MF │ └── maven │ └── cn.coderss │ └── reactive │ ├── pom.properties │ └── pom.xml └── org └── springframework └── boot └── loader ├── ExecutableArchiveLauncher$1.class ├── ExecutableArchiveLauncher.class ├── JarLauncher.class ........ ├── PropertiesLauncher.class ├── WarLauncher.class ├── archive │ ├── Archive$Entry.class ........ │ └── JarFileArchive.class ├── data │ ├── ByteArrayRandomAccessData.class ........... │ └── RandomAccessDataFile.class ├── jar │ ├── AsciiBytes.class ........... │ └── ZipInflaterInputStream.class └── util └── SystemPropertyUtils.class
Spring-Boot-Loader简介 Springboot中jar文件格式固定如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 archive.jar | +-META-INF(1) | +-MANIFEST.MF +-org(2) | +-springframework | +-boot | +-loader | +-<spring boot loader classes> +-com(3) | +-mycompany | + project | +-YouClasses.class +-lib(4) +-dependency1.jar +-dependency2.jar
结构(1)jar文件中MANIFEST.MF文件存放处
结构(2) Spring-boot-loader本身需要的class放置处
结构(3) 应用本身的文件放置处
结构(4)应用依赖的jar固定放到lib目录。
那么spring-boot是如何去按照这个结构加载资源那?
首先在打包时候会使用spring-boot-maven-plugin插件重写打成的jar文件,会设置META-INF/MANIFEST.MF中的Main-Class: org.springframework.boot.loader.JarLauncher
Start-Class: com.mycompany.project.MyApplication
并拷贝spring-boot-loader包里面的class文件到结构(2),应用依赖拷贝到(4)应用类拷贝到(3)
通过java -jar archive.jar 运行时候Launcher会去加载JarLauncher类并执行其中的main函数,JarLauncher主要关心构造一个合适的URLClassLoader加载器用来调用我们应用程序(MyApplication)的main方法。
spring-boot-maven-plugin打包流程
JarLauncher执行流程分析
如流程图首先使用Appclassloader加载了JarLauncher类并创建了LaunchedURLClassLoader类
而LaunchedURLClassLoader是属于spring-boot-loader.jar包里面的
而Appclassloader是普通的加载器不能加载嵌套的jar里面的文件
所以如果把spring-boot-loader.jar放到lib 目录下,Appclassloader将找不到LaunchedURLClassLoader。
所以在打包时候 拷贝本来应该放入到lib里面的spring-boot-loader.jar里面的class到结构(2)
LaunchedURLClassLoader LaunchedURLClassLoader和普通的URLClassLoader的不同之处是,它提供了从JarFile里加载.class的能力。结合Archive提供的getEntries函数,就可以获取到JarFile里的Resource。
1 2 Jar URL jar:file:/tmp/target/demo-0.0 .1-SNAPSHOT.jar!/com/example/SpringBootDemoApplication.class
jar包里的资源的URL;可以看到对于Jar里的资源,定义以’!/’来分隔。原始的JarFile URL只支持一个’!/’。
Spring boot扩展了这个协议,让它支持多个’!/’,就可以表示jar in jar,jar in directory的资源了。
1 2 Jar URL jar:file:/tmp/target/demo-0.0 .1-SNAPSHOT.jar!/lib/spring-beans-4.2 .3.RELEASE.jar!/META-INF/MANIFEST.MF
Spring boot通过注册了一个自定义的Handler类来处理多重jar in jar的逻辑。
自定义URLStreamHandler,扩展JarFile和JarURLConnection
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public class Handler extends URLStreamHandler { private static final String SEPARATOR = "!/" ; private static SoftReference<Map<File, JarFile>> rootFileCache; @Override protected URLConnection openConnection (URL url) throws IOException { if (this .jarFile != null ) { return new JarURLConnection(url, this .jarFile); } try { return new JarURLConnection(url, getRootJarFileFromUrl(url)); } catch (Exception ex) { return openFallbackConnection(url, ex); } } public JarFile getRootJarFileFromUrl (URL url) throws IOException { String spec = url.getFile(); int separatorIndex = spec.indexOf(SEPARATOR); if (separatorIndex == -1 ) { throw new MalformedURLException("Jar URL does not contain !/ separator" ); } String name = spec.substring(0 , separatorIndex); return getRootJarFile(name); } }
Spring boot构造LaunchedURLClassLoader时,传递了一个URL[]数组。数组里是lib目录下面的jar的URL
实际流程如下:
1 2 3 4 5 6 7 8 9 @Override public InputStream getInputStream () throws IOException { connect(); if (this .jarEntryName.isEmpty()) { throw new IOException("no entry name specified" ); } return this .jarEntryData.getInputStream(); }
总结 从一个URL,到最终读取到URL里的内容,整个过程是比较复杂的,总结下:
spring boot注册了一个Handler来处理”jar:”这种协议的URL
spring boot扩展了JarFile和JarURLConnection,内部处理jar in jar的情况
在处理多重jar in jar的URL时,spring boot会循环处理,并缓存已经加载到的JarFile
对于多重jar in jar,实际上是解压到了临时目录来处理,可以参考JarFileArchive里的代码
在获取URL的InputStream时,最终获取到的是JarFile里的JarEntryData
Reactive Servlet3.1异步机制
一个ServletRequest
可以通过调用 request.startAsync()
被放到一个异步的模块中.这样做的主要作用是Servlet,以及任何过滤器,可以退出,但是响应仍将允许开放直到处理完成后。
调用request.startAsync()
返回AsyncContext
可以用于进一步控制异步处理。例如,它提供一个方法叫dispatch
,这个类似于Servlet API,并且它允许应用程序通过Servlet容器线程继续请求处理。
ServletRequest
提供获取当前DispatcherType
的接口.DispatcherType可以用来区分处理初始请求,一个异步分发,forward,以及其他分发类型。
记住上面的,下面是通过Callable
异步请求处理事件的序列:
Controller返回一个Callable
对象.
Spring MVC开始异步处理并且提交Callable
到TaskExecutor
在一个单独的线程中进行处理。
DispatcherServlet
与所有的Filter的Servlet容器线程退出,但Response仍然开放。
Callable
产生结果并且Spring MVC分发请求给Servlet容器继续处理.
DispatcherServlet
再次被调用并且继续异步的处理由Callable产生的结果
DeferredResult
的处理顺序与Callable十分相似,由应用程序多线程产生异步结果:
Controller返回一个DeferredResult
对象,并且把它保存在内在队列当中或者可以访问它的列表中。
Spring MVC开始异步处理.
DispatcherServlet
与所有的Filter的Servlet容器线程退出,但Response仍然开放。
application
通过多线程返回DeferredResult
中sets值.并且Spring MVC分发request
给Servlet
容器
DispatcherServlet
再次被调用并且继续异步的处理产生的结果.
异步支持模式 SpringMVC对Servlet3异步请求的支持有两种方式
Callable
1 2 3 返回方法是Callable类型时会默认发起异步请求 并使用一个TaskExecutor来调用返回的Callable 之后的处理就跟正常的SpringMVC请求是一样的
1 2 3 4 5 6 7 @GetMapping ("callable" )public Callable<String> callable () { return ()->{ TimeUnit.SECONDS.sleep(1 ); return "callable" ; }; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 RequestMappingHandlerAdapter#handleInternal->RequestMappingHandlerAdapter#invokeHandlerMethod ServletInvocableHandlerMethod#invokeAndHandle CallableMethodReturnValueHandler#handleReturnValue WebAsyncManager#setConcurrentResultAndDispatch WebAsyncManager#this.asyncWebRequest.dispatch(); RequestMappingHandlerAdapter#invokeHandlerMethod if (asyncManager.hasConcurrentResult()) { Object result = asyncManager.getConcurrentResult(); mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0 ]; asyncManager.clearConcurrentResult(); if (logger.isDebugEnabled()) { logger.debug("Found concurrent result value [" + result + "]" ); } invocableMethod = invocableMethod.wrapConcurrentResult(result); }
DeferredResult
步骤如上差不多
1 2 3 4 5 6 7 8 9 10 @GetMapping ("deferredResult" )public DeferredResult<String> deferredResult () { DeferredResult<String> deferredResult = new DeferredResult<>(); new Thread(() -> deferredResult.setResult("ok" )).start(); deferredResult.onCompletion(()->{ log.info("completion" ); }); return deferredResult; }
Rxjava+Deferred Result
利用Rxjava的线程调度
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 @Configuration public class WebMvcConfig extends WebMvcConfigurerAdapter { @Override public void addResourceHandlers (ResourceHandlerRegistry registry) { registry.addResourceHandler("/resources/**" ).addResourceLocations("static" ); } @Override public void addReturnValueHandlers (List<HandlerMethodReturnValueHandler> returnValueHandlers) { returnValueHandlers.add(new ObservableReturnValueHandler()); } } public class ObservableReturnValueHandler implements AsyncHandlerMethodReturnValueHandler { @Override public boolean isAsyncReturnValue (Object returnValue, MethodParameter returnType) { return supportsReturnType(returnType); } @Override public boolean supportsReturnType (MethodParameter returnType) { return Observable.class.isAssignableFrom(returnType.getParameterType()); } @Override public void handleReturnValue (Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception { final Observable<?> observable = Observable.class.cast(returnValue); WebAsyncUtils.getAsyncManager(webRequest) .startDeferredResultProcessing(new ObservableAdapter<>(observable), mavContainer); } public class ObservableAdapter <T > extends DeferredResult <T > { ObservableAdapter(Observable<T> observable) { observable.subscribe(this ::setResult, this ::setErrorResult); } } } @GetMapping ("/" )public Observable<IndexVO> index () { return indexService .getMessage("San" ) .map((data)->IndexVO.builder().message(data.getMessage()).build()); }
异步拦截 一个HandlerInterceptor
可样也可以实现AsyncHandlerInterceptor
,通过实现它的afterConcurrentHandlingStarted
方法进行回调.当进行异步处理的时候,将会调用afterConcurrentHandlingStarted
而不是postHandle
和afterCompletion
.
一个HandlerInterceptor
同样可以注册CallableProcessingInterceptor
或者一个DeferredResultProcessingInterceptor
用于更深度的集成异步request的生命周期.例如处理一个timeout事件.你可以参看AsyncHandlerInterceptor
的Javadoc了解更多细节.
DeferredResult
类也提供了方法,像onTimeout(Runnable)
和onCompletion(Runnable)
.可以看DeferredResult了解更多细节.
当使用Callable
的时候,你可以通过WebAsyncTask
来对它进行包装.这样也可以提供注册timeout与completion方法.
HTTP Streaming ResponseBodyEmitter
允许通过HttpMessageConverter
把发送的events写到对象到response中
例如写JSON数据.可是有时候它被用来绕开message转换直接写入到response的OutputStream
。
例如文件下载.这样可以通过返回StreamingResponseBody
类型的值做到.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @RequestMapping ("/events" )public ResponseBodyEmitter handle () { ResponseBodyEmitter emitter = new ResponseBodyEmitter(); return emitter; } emitter.send("Hello once" ); emitter.send("Hello again" ); emitter.complete();
转自csdn
国内查看评论需要代理~