spring 笔记

6 篇文章 0 订阅
spring ApplicationContext
    ApplicationContext extends ListableBeanFactory, HierarchicalBeanFactory, EnvironmentCapable, ResourcePatternLoader, MessageSource, ApplicationContextPublisher
    ListableBeanFactory 获取BeanDefinition 集合
    HierarchicalBeanFactory 设置parentFactory
    EnvironmentCapable 获取环境 getActiveProfile(ConfigurableApplicationContext setEnvironment)
    ResourcePatternLoader 加载资源文件 spring.xml
    MessageSource 国际化
    ApplicationContextPublisher 提供发布订阅功能
    ApplicationContext 本身定义了一些获取 application id, name, parent context接口, 由ConfigurableApplicationContext 提供

    ConfigurableApplicationContext extends ApplicationContext
    ConfigurableApplicationContext is a SPI, 主要配置一些 applicationContext id name, parent context, Environment, BeanFactoryPostProcessor, ApplicationListener,
    refresh() load or refresh xml,property, database schema 等信息
    getBeanFactory(): ConfigurableListableBeanFactory ApplicationContext internal  bean factory


    AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext
     use Template Method design pattern,
     该类主要拥有的属性,
     String id,
     String displayName,
     ApplicationContext parent,
     ConfigurableEnvironment environment,
     List<BeanFactoryPostProcessor> beanFactoryPostProcessors,
     ResourcePatternResolver resourcePatternResolver,
     Set<ApplicationListener<?>> applicationListeners,
     MessageSource messageSource,
     Set<ApplicationListener<?>> earlyApplicationListeners

     关于refresh 方法, 执行步骤
     1. preRefresh()
        设置当前ApplicationContext
        startupDate=System.currentTimeMillis()
        closed.set(false)
        active.set(true)
        开启debug日志
        initPropertySources() Initialize any placeholder property sources in the context environment. 让子类实现
        getEnvironment().validateRequiredProperties()
        初始化earlyApplicationListeners earlyApplicationEvents
     2. obtainFreshBeanFactory()
        Tell the subclass to refresh the internal bean factory. refresh 内部ConfigurableListableBeanFactory
        obtainFreshBeanFactory(), refreshBeanFactory() 让子类去实现refresh内部BeanFactory 并返回
     3. prepareBeanFactory(beanFactory)
        Prepare the bean factory for use in this context.
        主要为内部BeanFactory(ConfigurableListableBeanFactory) 初始化 一些 默认实现的数据,包括classLoader, BeanExpressionResolver, ResourceEditorRegistrar
        ApplicationContextAwareProcessor(该类主要是各种Aware接口注入对应的对象, BeanPostProcessor),  Register default environment beans.
     4. postProcessBeanFactory(beanFactory)
        该方法是在内部BeanFactory 实例化 但未初始化时 修改内部BeanFactory实例属性.
        Modify the application context's internal bean factory after its standard initialization.Allows post-processing of the bean factory in context subclasses.
        All bean definitions will have been loaded, but no beans will have been instantiated yet, This allows for registering special BeanPostProcessors

     5. invokeBeanFactoryPostProcessors(beanFactory) ---- 实例化所有的BeanFactoryPostProcessor 并且调用
        Instantiate and invoke all registered BeanFactoryPostProcessor beans in the context,

     6. registerBeanPostProcessors(beanFactory)  ---- 实例化所有的BeanPostProcessor 并注册到applicationContext中, 在所有的application beans 实例化之前调用
        Register bean processors that intercept bean creation.  Instantiate and register all BeanPostProcessor beans, respecting explicit order if given.
        Must be called before any instantiation of application beans.

     7. initMessageSource() 创建的实例对象 注册到getBeanFactory() inner BeanFactory 中

     8. initApplicationEventMulticaster() 创建的实例对象 注册到getBeanFactory() 中

     9. onRefresh()
         Initialize other special beans in specific context subclasses. 用于 扩展使用
     10. registerListeners()
         用于监听ApplicationEventMulticaster(manage ApplicationEventListener,  and publish events to them) 广播的ApplicationEvent

     11. finishBeanFactoryInitialization(beanFactory)
        Instantiate all remaining (non-lazy-init) singletons.

     12. finishRefresh()
         Last step: publish corresponding event



AbstractRefreshableApplicationContext extends AbstractApplicationContext:
    属性 DefaultListableBeanFactory beanFactory, Bean factory for this context.
    refreshBeanFactory:
        实现方法, 初始化DefaultListableBeanFactory, 每次调用refreshBeanFactory() 重新创建, loadBeanDefinitions(beanFactory)



AbstractRefreshableConfigApplicationContext:
    String[] configLocations
    实现了InitializingBean, 在afterPropertiesSet() Triggers refresh() if not refreshed in the concrete context's constructor already.




ConfigurableListableBeanFactory extends ListableBeanFactory, ConfigurableBeanFactory, AutowireCapableBeanFactory
       ConfigurableBeanFactory, 配置BeanPostProcessor, PropertyEditorRegistry, BeanExpressionResolver,  ConversionService, parentBeanFactory
       AutowireCapableBeanFactory, 可以wire 非spring管理的bean,  ApplicationContext.getAutowireCapableBeanFactory, this interface is not implemented by ApplicationContext


AutowireCapableBeanFactory:
    resolveNamedBean



以ClassPathXmlApplicationContext为例:
new ClassPathXmlApplicationContext(String path)执行过程:
    1. 调用父类构造器 设置parent
    2. setConfigLocations, xml文件路径
    3. 调用refresh 方法, refresh方法的实现在AbstractApplicationContext类中
        AbstractApplicationContext.refresh():
            1. preRefresh() 设置ApplicationContext 启动时间, 状态, Environment
            2. obtainFreshBeanFactory(), 构造 创建DefaultListableBeanFactory后, 调用AbstractRefreshableApplicationContext.refresh()发方法
                创建DefaultListableBeanFactory后执行loadBeanDefinition(beanFactory), 因为是ClassPathXmlApplicationContext 所以默认的实现是XmlBeanDefinitionReader
                去读取Resource解析并设置到DefaultListableBeanFactory的Map beanDefinitionMap中
            3. prepareBeanFactory(beanFactory) 将当前的ApplicationContext的一些配置设置到beanFactory中以及
                ignoreDependencyInterface registerResolvableDependency addBeanPostProcessor(ApplicationListenerDetector),
                Register default environment beans.
            4. postProcessBeanFactory(beanFactory) 具体的ApplicationContext实现该方法, 比如webApplicationContext添加ignoreDependencyInterface(ServletContextAware)等

            5. invokeBeanFactoryPostProcessors(beanFactory)
                Invoke factory processors registered as beans in the context, inner BeanFactory and ApplicationContext BeanFactoryPostProcessor 一起按照PriorityOrdered, Ordered执行
                会先执行BeanFactoryDefinitionPostProcessor 在执行普通的BeanFactoryPostProcessor(ApplicationContext BeanFactoryPostProcessor不会被inner BeanFactory管理)
            6. registerBeanPostProcessors(beanFactory)
                注册BeanPostPorcessor到inner BeanFactory(AbstractBeanFactory)
            7. initMessageSource()
            8. initApplicationEventMulticaster()
            9. onRefresh()
                template method, 留给子类overwrite
            10. registerListeners()
            11.finishBeanFactoryInitialization(beanFactory)
                 Instantiate all remaining (non-lazy-init) singletons.(个人猜测 BeanFactoryPostProcessor, BeanPostProcessor 已经被instantiated)

            12. finishRefresh()
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
DefaultListableBeanFactory:


AnnotationAwareAspectJAutoProxyCreator


------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Bean的创建过程, 如何通过BeanDefinition获得Bean
从AbstractBeanFactory.getBean(String) 开始, 获取beanName对应的BeanDefinition, 查看BeanDefinition的Dependence, 如果有Dependece的先getBean 去创建dependence,
获取BeanDefinition, 调用AbstractAutowireCapableBeanFactory.createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)方法, 这个方法很重要,
该方法包含了创建bean,填充bean的属性以及调用post-processors等等, 初始化bean有2中方式, 一种autowireConstructor(beanName, mbd, null, null), 这种方法是调用带构造参数的构造器
实例化bean, 第二种instantiateBean(beanName, mbd)使用默认无参构造器实例化bean, 但最终还是使用InstantiationStrategy.instantiate 来实例化bean, AbstractAutowireCapableBeanFactory
默认的是CglibSubclassingInstantiationStrategy extends SimpleInstantiationStrategy, 如果!bd.hasMethodOverrides()即没有overrides的方法(应该是没有设置对应的aop)直接通过反射调用
构造器创建bean, 否则通过Enhancer 创建对应的subClass 生成enhancer object 代理对象并通过Factory接口设置callbacks, 实例化bean后封装到BeanWrapper中, 默认为BeanWrapperImpl, initBeanWrapper
设置conversionService和registerCustomEditors
AbstractAutowireCapableBeanFactory 包含了创建bean的JdkRegexpMethodPointcut所有过程, 包括实例化bean, populateBean(包括 autowire), initailizeBean(调用invokeAwareMethods, BeanPostProcessor and InitailizeBean)


AutowiredAnnotationBeanPostProcessor用来处理@Autowired @Value, 在AbstractAutowireCapableBeanFactory.populateBean方法中使用

CommonAnnotationBeanPostProcessor用来处理jsr中定义的规范@Inject @Resource等

ConfigurationClassPostProcessor registry @Configuration 中声明的BeanDefinition

ContextAnnotationAutowireCandidateResolver extends SimpleAutowireCandidateResolver 用来获取@Value中的SpEl表达式${}, 然后通过 PropertyResolver解析比如从.properties文件获取对应的String value值

PropertySourcesPlaceholderConfigurer.postProcessBeanFactory 主要作用就是从.properties文件获取值并设置到对应的BeanDefinition中
PlaceholderResolvingStringValueResolver 默认的构造参数Properties, 包含了.properties文件中的值, 可以解析出${} String值, 再通过PropertyEditor或者ConversionService转换为
对应的数据类型并设置到BeanDefinition中的PropertyValue.convertedValue上, 而@Value 这种形式是通过AutowiredAnnotationBeanPostProcessor 是动态的解析@Value的值, 先通过AutowireCandidateResolver
获取@Value的值, AbstractBeanFactory.embeddedValueResolvers循环解析,  embeddedValueResolvers有2个地方设置, 一个是在PlaceholderConfigurerSupport.doProcessProperties方法中
beanFactoryToProcess.addEmbeddedValueResolver(valueResolver),  也就是PropertySourcesPlaceholderConfigurer.postProcessBeanFactory方法中, 另一个实在AbstractApplicationContext.finishBeanFactoryInitialization
如果embeddedValueResolvers 为空, 就默认使用strVal -> getEnvironment().resolvePlaceholders(strVal), 此处使用的是lamda表达式, 这种解析方法为getEnvironment().resolvePlaceholders(strVal),
AbstractEnvironment中默认的PropertySourcesPropertyResolver.resolvePlaceholders, PropertySourcesPropertyResolver的默认构造参数PropertyValues, 应该也是从.properties文件中加载而来, 第一种就和
PropertySourcesPlaceholderConfigurer通过PlaceholderResolvingStringValueResolver一样

------------------------------------------------------------------------------------------------------------------------------------------------------------------------
AnnotationConfigApplicationContext
AnnotationConfigApplicationContext extends GenericApplication 所有 DefaultListableBeanFactory 只会创建一次, 可以多次从不同的resource format loadBeanDefinitions,
AnnotationConfigApplicationContext 需要手动的设置register(config class) 或者scan(package), Config class 就会通过AnnotatedBeanDefinitionReader被加载为BeanDefinition,
此时config class 内声明的bean 对应的BeanDefinition 还未被加载到BeanFactory, 需要通过ConfigurationClassPostProcessor这个BeanDefinitionRegistryPostProcessor的调用来解析,
ConfigurationClassPostProcessor是 BeanFactoryPostProcessor也是BeanDefinitionRegistryPostProcessor优先于普通的 BeanFactoryPostProcessor.当所有的Config class中的beanDefinition
都加载到DefaultListableBeanFactory中后,对于bean的创建都是在AbstractAutowireCapableBeanFactory中实现的

ConfigurationClassPostProcessor
config class可以配置@Configuration @Import @ImportResource @PropertySource
ConfigurationClassPostProcessor主要通过ConfigurationClassBeanDefinitionReader loadBeanDefinition from config class, 对于@ImportResource 为.xml(.properties应该包含)使用XmlBeanDefinitionReader
.groovy使用GroovyBeanDefinitionReader, @Import 还是使用ConfigurationClassBeanDefinitionReader, 对于@PropertySource 所加载的资源是被设置到Environment中, 在ConfigurationClassPostProcessor解析加载
BeanDefinition前通过ConfigurationClassParser将.properties文件设置到了Environment当中, 所以默认的AnnotationConfigApplicationContext没有使用PropertySourcesPlaceholderConfigurer,
PropertySourcesPlaceholderConfigurer主要是在实例化bean之前修改了BeanDefinition, 将对应的property 设置到了BeanDefinition.propertyValue, 而通过@Configuration这种方式BeanDefinition中没有PropertyValue,
是使用InjectedElement,通过反射, 普通方式是使用wri对EnableConfigteMethod. 对于xmlApplicationContext property要设置set方法, 而AnnotationApplicationContext 却不需要.
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ApplicationContext 对于Aop的代理对象创建解析
AnnotationAwareAspectJAutoProxyCreator BeanPostProcessor, ProxyFactory 创建代理对象, CGlib 对于MethodInterceptor 的实现为methodProxy.invoke(targetObj, args), 因此对于拦截的嵌套方法this的指向为targetObj
所以只会执行一次, cglib是直接通过targetObj调用而非反射, JDk dynamic 而是通过反射调用所以内嵌方法更不会被拦截.....


------------------------------------------------------------------------------------------------------------------------------------------------------------------------
spring Lifecycle 一般是用来启动异步工作, 比如Scheduler在ApplicationContext refresh完成后通过onRefresh接口调用LifecycleProcessor找到SmartLifecycle启动shceduler任务


------------------------------------------------------------------------------------------------------------------------------------------------------------------------
XmlWebApplicationContext
适用于servlet web环境, 持有ServletContext 和ServletConfig 属性(默认就一个DispatcherServlet), 基本和ClasspathXmlApplicationContext 没什么区别.
在web环境中通过ServletContextListener.contextInitialized 事件监听器 来创建XmlWebApplicationContext, 从ServletContext 中获取spring.xml文件, config and refresh applicationContext
将XmlWebApplicationContext设置到ServletContext的WebApplicationContext.class.getName() + ".ROOT"

------------------------------------------------------------------------------------------------------------------------------------------------------------------------
DispatcherServlet extends FrameworkServlet
属于HttpServlet, 由于HttServlet的实例化工作由Servlet容器执行, 所有spring通过Servlet的生命周期在init这个过程扩展, 为DispatcherServlet构造了WebApplicationContext作为一个属性, 并设置ServletContext
中的WebApplicationContext为Parent, 所以关于web层的组件可以生命在DispatcherServlet的上下文中, 如HandlerMapping, HandlerAdapter, ViewResolver, MultipartResolver, HandlerExceptionResolver,
当然这些已经在DispatcherServlet中通过DispatcherServlet.properties中设置了一些默认值, 基本上已经够了, 其实在设置<mvc:annotation-driven/> 或者@EnableWebMvc时已经通过AnnotationDrivenBeanDefinitionParser
设置了一部分.
DispatcherServlet最重要的处理逻辑主要在doDispatch中, 通过HandlerMapping获取HandlerExecutionChain, 从HandlerExecutionChain.HandlerMethod找到合适的HandlerAdapter, 依次调用HandlerExecution的
HandlerInterceptor.preHandle, HandlerAdapter.handle, HandlerInterceptor.postHandle, HandlerInterceptor.afterCompletion.
DispatcherServlet主要使用的HandlerMapping为RequestMappingHandlerMapping, 如何通过request来获取对应HandlerMethod? 在RequestMappingHandlerMapping 通过afterPropertySet方法初始化所有并存储在
MappingRegistry中
HandlerAdapter默认使用RequestMappingHandlerAdapter, 主要作用是使用DataBinder将request中的数据绑定到方法的请求参数中包括HttpServletRequest和HttpServletResponse, 对于数据的转换使用PropertyEditory
和ConversionService, 抽象到BeanWrapper中来完成.

------------------------------------------------------------------------------------------------------------------------------------------------------------------------
servlet3.0 支持注解加载Servlet, Filter,同时可以编程式的编写servlet到ServletContext中, ServletContextInitializer.onStart, spring提供了对DispatcherSerlet的加载注册实现,
ApplicationContextInitializer

------------------------------------------------------------------------------------------------------------------------------------------------------------------------
springboot 启动流程: 一般通过SpringApplication.run(String[] args)来初始化ApplicationContext 和启动webserver , 具体的步骤在SpringApplication.run方法中, 初始化SpringApplicationRunListeners,
ConfigurableEnvironment, Banner, 创建ApplicationContext(此时的ApplicationContext 只默认设置里一些BeanDefinitionPostProcessor, 没有对应的资源文件, refresh方法也没有调用), prepareContext 为ApplicationContext
设置一些参数(最主要的是加载@SpringBootApplication注解类的BeanDefinition), refresh, callRunners.
springboot 启动时默认的ApplicationContext为AnnotationConfigServletWebServerApplicationContext, 多了WebServer属性 定义在ServletWebServerApplicationContext, WebServer 是对Springboot
内嵌web server的抽象, 实现类包括TomcatWebServer, UndertowWebServer, NettyWebServer, JettyWebServer, 基本和AnnotationConfigWebApplicationContext类似, 多了对WebServer的创建, 在AbstractApplicationContext
refresh()方法 最后finishRefresh() 会启动WebServer.
springboot 中ApplicationContext只有一个AnnotationConfigServletWebServerApplicationContext,没有了父子上下文, 对于DispatcherServlet的创建由spring来控制.

springboot 对EnableAutoConfiguration的处理过程:
    在启动Springboot 项目时, 一般通过在main 方法所在的类声明@SpringBootApplication即可, 显然main 类就是ApplicationContext的主配置类, 并且main类带有SpringBootApplication注解, SpringBootApplication注解
    相当于@ComponentScan,@EnableAutoConfiguration, @Configuration 的组合, 在SpringApplication的构造函数中main 类被设置到了primarySources, sources上. 在创建AnnotationConfigServletWebServerApplicationContext
    后, 开始为refresh 方法准备, 在SpringApplication.run 方法中repareContext调用load方法将main类注册到了BeanFactory中, 然后开始refresh ApplicationContext, 调用AbstractApplicationContext.refresh 模板方法,
    关键方法invokeBeanFactoryPostProcessors(对于额外的BeanDefinition的加载一般是通过BeanDefinitionRegistryPostProcessor接口), 在ApplicationContext创建时Spring 默认添加了比较重要的3个BeanDefinitionPostProcessor,
    ConfigurationClassPostProcessor, AutowiredAnnotationBeanPostProcessor, CommonAnnotationBeanPostProcessor(这些是在AnnotatedBeanDefinitionReader创建时通过AnnotationConfigUtils.registerAnnotationConfigProcessors),
    对于main类的解析就由ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法处理, 首先从BeanFactory中获取所有的BeanDefinition names, 封装成BeanDefnitionHolder 交由ConfigurationClassParser来解析,
    在ConfigurationClassParser.parse(Set<BeanDefinitionHolder> configCandidates)分为两步, 一是对configCandidates遍历通过doProcessConfigurationClass处理, 然后DeferredImportSelectorHandler.process, 其实这两步
    都是对配置类的factory method, ImportResource 设置到ConfigurationClass中, 只不过一是对我们明确声明的配置类的加载, 二是对spring.factories 中声明的EnableAutoConfiguration 自我发现的配置类的加载(其实还需要在spring-autoconfigure-metadata.properties
    中声明). doProcessConfigurationClass 方法中依次对PropertySource,ComponentScan,Import,ImportResource,@Bean method进行处理, @PropertySource 将声明的location 对应的resource 加载到Environment,@ComponentScan
    通过ComponentScanAnnotationParser.parse 获取配置类集合Set<BeanDefinitionHolder>重复类似一的步骤, @Import 的处理时首先获取所有的@Import的value值包括所有的注解上声明的注解 此处就包括@EnableAutoConfiguration上的
    AutoConfigurationImportSelector, processImports 方法中分别对于ImportSelector, ImportBeanDefinitionRegistrar, 普通的importCandidates 特别处理, 对于此处的ImportSelector为AutoConfigurationImportSelector,
    主要作用是通过SpringFactoriesLoader从spring.factories加载@EnableAutoConfiguration class name, 通过AutoConfigurationMetadataLoader加载spring-autoconfigure-metadata.properties所有的class name, 通过
    AutoConfigurationImportFilter.match()选出需要Import 的class 最后还是调用processImport方法获取bean method, property source设置到ConfigurationClass 中(这步是在二中完成的). 当ConfigurationClassParser.parse
    完成后, ConfigurationClassBeanDefinitionReader 就会从ConfigurationClass中loadBeanDefinitions包括import resource 和ImportBeanDefinitionRegistrar中的BeanDefinition.此时对于所有的BeanDefinition 基本完成加载
    后续为对single bean的实例化和初始化.

springboot application.properties加载
    springApplication.run prepareEnvironment 通过SpringApplicationRunListeners.environmentPrepared基于事件配置environment, ConfigFileApplicationListener.onApplicationEvent 加载classpath, classpath:/config
    下的默认配置文件application.properties, application.yml, application.yaml 读取spring.profiles.active设置到Environment, 或者从args设置到Environemnt的profile 在去读取对应profile的配置文件   

springboot @EnableConfigurationProperties 和 ConfigurationProperties
    声明在@Configuration类上的@EnableConfigurationProperties, 在其对应的ConfigurationClass对象中importBeanDefinitionRegistrars设置2个BeanDefinitionRegistrar, ConfigurationPropertiesBeanRegistrar和
    ConfigurationPropertiesBindingPostProcessorRegistrar, 对应的AnnotationMetadata为当前@Configuration类注解信息. 在ConfigurationClassParser解析完所有的ConfigurationClass后, 通过ConfigurationClassBeanDefinitionReader
    加载注册BeanDefinition, 加载注册的最后2步为从ImportResource和BeanDefinitionRegistrar获取注册BeanDefinition.
    ConfigurationPropertiesBeanRegistrar注册BeanDefinition的过程: 首先找到@EnableConfigurationProperties的value class值, 获取该class 将要注册到BeanFactory中的name(如果class 有@ConfigurationProperties且prefix
    有值, name 为prefix+"-"+class.name,如果没有@ConfigurationProperties或prefix为空name则为class.name), 检测BeanFactory是否已包含给name对应的BeanDefinition, 有跳过,没有将该class 注册到BeanFactory中(如果class没有
    @ConfigurationProperties注解会报错, 做了一个Assert.notNull判断).
    ConfigurationPropertiesBindingPostProcessorRegistrar: ConfigurationPropertiesBindingPostProcessor,ConfigurationBeanFactoryMetadata 注册到BeanFactory. ConfigurationPropertiesBindingPostProcessor
    处理带有@ConfigurationProperties注解的bean, 从PropertySources获取prefix属性设置到bean中(通过set方法),
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值