一 . 容器
1.1 组件注册
- AnnotationConfigApplicationContext容器
- @ComponentScan
@Scope
- singleton:在工厂创建时就实例化对象,在容器关闭时销毁对象
- protoype:在使用对象的时候才实例化,容器不会进行管理,需要手动进行销毁实例
- @Lazy
@Conditional({MyCondition.class})
- 实现Condition接口中#matches(ConditionContext,AnnotatedTypeMetadata)来判断是否需要将实例注册到容器中
给容器中注册组件:
- 包扫描+组件标注注解(@controller/@service/@repository/@component)
- @Bean[导入的第三方包里面的组件]
@Import[快速给容器中导入一个组件]------SpringBoot自动装备的主要注入方式
@Import注解
- @Import({Color.class,MyImportSelector.class,MyImportBeanDefinitionRegistrar.class})
ImportSelector接口
- 配合Import注解,实现ImportSelector接口,在其selectImports方法中返回注册实例的全类名.
ImportBeanDefinitionRegistrar接口
配合Import注解.实现ImportBeanDefinitionRegistrar接口,在其#registerBeanDefinitions(AnnotationMetadata,BeanDefinitionRegistry)方法通过参数BeanDefinitionRegistry#registerBeanDefinition(String , BeanDefinition)来注册Bean实例
public class MyImportBeanDefinitionRegistrar implement ImportBeanDefinitionRegistrar{ public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,BeanDefinitionRegister registry){ boolean definition1 = registry.containBeanDefinition("red"); boolean definition2 = registry.containBeanDefinition("blue"); if(definition1 && definition2){ RootBeanDefinition beanDefinition = new RootBeanDefinition(Yellow.class); registry.registerBeanDefinition("rainBow",beanDefinition) } } }
使用Spring提供的FactoryBean(工厂Bean)
- 实现FactoryBean接口,在#getObject()中返回要创建的实例Bean对象
将定义的FactoryBean的实例对象通过@Bean注解将工厂注入到容器中
- 通过工厂实例id获取到的对象为Bean对象
- 如果要获取工厂对象则需要在id前加上&
1.2 生命周期
Bean的生命周期:
- bean创建---初始化---销毁的过程
容器管理bean的生命周期:
初始化和销毁方法:容器在bean进行到当前生命周期的时候来调用我们自定义的初始化方法和销毁方法
1. XML:<Bean init-method=" " destroy-method=" "> 2. Bean注解:@Bean(initMethod="init",destroyMethod="destroy") 3. InitializingBean接口和DisposableBean接口 * 通过实现InitializingBean接口#afterPropertiesSet() * 通过实现DisposableBean接口#destroy() 4. 通过JSR250@PostConstruct注解和@PreDestroy注解 5. 通过Bean后置处理器BeanPostProcessor * postProcessBeforeInitialization():在创建实例之后,且在任何初始化方法调用之前进行处理 * postProcessAfterInitialization():在初始化方法之后进行处理 * 注意:通过debug来跟踪spring实例化的过程 * populateBean(beanName,mbd,instanceWrapper):给bean进行属性复制 * applyBeanPostProcessorsBeforeInitialization(wrappedBean,beanName) * invokeInitMethods(beanName,wrappedBean,mbd):执行自定义初始化方法 * applyBeanPostProcessorAfterInitialization(wrappedBean,beanName)
Bean后置处理器BeanPostProcessor底层使用
ApplicationContextAwareProcessor:注册ApplicationContextAware接口
- 实现ApplicationContextAwareProcessor接口后,在初始化之前会将ApplicationContext注入到实现ApplicationContextAware接口的实例中
- CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBeanPostProcessor:@PostConstruct和@PreDestroy注解
- AutowiredAnnotationBeanPostProcessor:@Autowired注解
1.3 属性赋值
@value
- 基本数值:String
- SPEL:#{ }
- 配置文件或运行环境中的值:${ }
导入配置信息
- XML导入配置文件:<context:property-placeholder location="classpath:person.properties">
- 注解导入配置文件:@PropertySource({"classpath:person.properties"})
- 注解导入配置类:@EnablePropertyConfiguration(MyConfiguration.class)
1.4 自动装配
Spring利用依赖注入(DI),完成对IOC容器中各个组件的依赖关系赋值
@Autowired和@qualifer和@primary
- @Autowired有required属性和@primary注解功能
JSR@Resource注解和JSR330@Inject注解
- @Resource无required属性和@primary注解功能
- @Inject有@Primary注解功能,但是无required属性
Aware注入Spring底层组件
- 通过自定义组件实现xxxAware接口,在创建对象的时候,以回调的方式注入相关组件
@Profile:Spring为我们提供的可以根据当前环境,动态的激活和切换一系列组件的功能
@Profile:指定组件在哪个环境下才能被注册到容器
- 使用命令行动态参数---VM arguments:-Dspring.profiles.active=dev
使用容器
- 创建一个无参的容器实例:applicationContext = new AnnotationConfigApplicationContext();
- 设置需要激活的环境:applicaionContext.getEnvironment().setActiveProfiles();
- 注册主配置类:applicationContext.register(MainConfigOfProfile.Class);
- 启动刷新容器:applicationContext.refresh();
1.5 AOP
AOP:面向切面编程,指在程序运行期间动态的将某段代码切入到指定方法或指定位置进行运行的编程方式.
通知方法
- 前置通知---@Before:在目标方法运行之前运行
- 后置通知---@After:在目标方法运行结束之后运行---无论是正常结束还是异常结束
返回通知---@AfterReturning:在目标方法正常返回之后运行
- @AfterReturning(value="pointCut()" , returning="result"),可以自己封装返回值
- public void logReturn(JoinPoint joinPoint , Object result){...}
异常通知---@AfterThrowing:在目标方法出现异常以后运行
- @AfterThrowing(value="pointCut()" , throwing="exception")
- public void logException(JoinPoint joinPoint , Exception exception){...}
环绕通知---@Around:动态代理,手动推进目标方法运行(joinPoint.proceed())
- 注:每个方法参数都可以注入JoinPoint,且必须在第一位
AOP原理分析
AOP原理:看给容器中注册了什么组件,这个组件什么时候工作,这个组件的功能是什么.
@EnableAspectJAutoProxy
- @EnableAspectJAutoProxy注解上@Import(AspectJAutoProxyRegistrar.class):给容器中导入AspectJAutoProxyRegistrar实例
AspectJAutoProxyRegistrar Implement ImportBeanDefinitionRegistrar
- BeanDefinitionRegistrar#registerBeanDefinitions(AnnotationMetadata , BeanDefinitionRegistry)中根据条件判断是否需要使用BeanDefinitionRegistry#register来注册AOP需要组件实例
- 在AspectJAutoProxyRegistrar#registerBeanDefinitions中注册了AnnotationAwareAspectJAutoProxyCreator的定义
AnnotationAwareAspectJAutoProxyCreator
-> extends AspectJAwareAdvisorAutoProxyCreator
->extends AbstractAdvisorAutoProxyCreator
-> extends AbstractAutoProxyCreator
-> implements SmartInstantiationAwareBeanPostPorcessor,BeanFactoryAware
关注后置处理器(SmartInstantiationAwareBeanPostPorcessor)和自动装配(BeanFactoryAware)
AbstractAutoProxyCreator:
- AbstractAutoProxyCreator#setBeanFactory()
- AbstractAutoProxyCreator#postProcessBeforeInstantiation()
AbstractAdvisorAutoProxyCreator:
- AbstractAdvisorAutoProxyCreator#setBeanFactroy()--->initBeanFactroy()
- AspectJAwareAdvisorAutoProxyCreator
AnnotationAwareAspectJAutoProxyCreator:
- AnnotationAwareAspectJAutoProxyCreator#initBeanFactory()
AOP通过@EnableAspectJAutoProxy创建AnnotationAwareAspectJAutoProxyCreator的流程
- 通过配置类,创建AnnotationConfigApplicationContext容器
通过AnnotationConfigApplicationContext有参构造器
- 创建无参容器
- 注册配置类
- 调用refresh()
refresh刷新容器
registerBeanPostProcessors(beanFactory):注册bean的后置处理器来拦截bean的创建
- 先获取ioc容器已经定义了的需要创建对象的所有BeanPostProcessor的定义(非实例对象)
给容器中添加别的BeanPostProcessor
- 优先注册实现了PriorityOrdered接口的BeanPostProcessor
然后注册实现Order接口的BeanPostProcessor,如internalAutoProxyCreator的BeanPostProcessor---AnnotationAwareAspectJAspectAutoPorxyCreator
- 获取Bean的实例,如果不存在就通过BeanDefinition创建Bean的实例#createBeanInstance()
- 通过populateBean()给Bean的属性赋值
initializeBean(),初始化Bean
- invokeAwareMethods():处理Aware接口的方法回调
- applyBeanPostProcessorsBeforeInitialization():执行后置处理器的postProcessorBeforeInitialization
- invokeInitMethods():执行自定义的初始化方法
- applyBeanPostProcessorsAfterInitialization():执行后置处理器的postProcessorAfterInitialization
- BeanPostProcessor(AnnotationAwareAspectJAspectAutoPorxyCreator)创建成功
- 最后注册其他的BeanPostProcessor
AOP创建代理对象的流程
- AnnotationAwareAspectJAutoProxyCreator => InstantiationAwareBeanPostProcessor extends BeanPostProcessor
finishBeanFactoryInitialization(beanFactory):完成BeanFactory初始化工作,创建剩下的Bean实例
遍历获取容器中所有的BeanName名称,通过名称获取BeanDefinition依次创建对象getBean(beanName)
- getBean()---doGetBean()---getSingleton(beanName , createBean())
创建Bean:
- 先从缓存中获取当前bean,如果能获取到,说明bean是之前被创建过的,直接使用,否则再创建新的,并且存入缓存
createBean():创建Bean
resolveBeforeInstantiation(beanName,mbdToUse):解析BeforeInstantiation,希望后置处理器在此能返回一个代理,如果能正常返回一个代理对象就使用,如果不能就继续创建---此初就是AOP创建代理对象的地方
applyBeanPostProcessorBeforeInstantiation(targetType,beanName)
- 获取所有的BeanPostProcessor,遍历集合,如果BeanPostProcessor instanceof InstantiationAwareBeanPostProcessor,则执行器处理器方法---例如:AnnotationAwareAspectJAutoProxyCreator#postProcessorBeforeInstantiation()
applyBeanPostProcessorAfterInstantiation(targetType,beanName)
- 获取所有的BeanPostProcessor,遍历集合,如果BeanPostProcessor instanceof InstantiationAwareBeanPostProcessor,则执行器处理器方法---例如:AnnotationAwareAspectJAutoProxyCreator#postProcessorAfterInstantiation()
- 注意:BeanPostProcessor是在Bean对象创建完成初始化前后调用的,而InstantiationAwareBeanPostProcesso是在任何Bean实例创建之前先尝试用后置处理器返回对象的代理对象
- doCreateBean(beanName,mbdToUse,args):真正的去创建一个bean实例
AnnotationAwareAspectJAutoProxyCreator#postProcessorBeforeInstantiation()
每一个bean创建之前,调用InstantiationAwareBeanPostProcessor实现的postProcessBeforeInstantiation()-----例如当对象是Mathcalculator和LogAspect时
- 判断当前bean是否在adviseBeans中,此集合保存了所有需要且已经增强的bean,若已经创建则返回,否则往下继续执行
判断是否为基础类型
- Advice
- PointCut
- Advisor
- AopInfrastructureBean
- 是否是切面---是否含有@Aspect注解
是否需要skip跳过
- 获取候选的增强器(切面里的通知方法)---List<Advisor> candidateAdvisors,其中每一个封装的通知方法的增强器是InstantiationModelAwarePointcutAdvisor
- 而跳过的判断为:当增强器类型是AspectJPointcutAdvisor类型时返回true,所以全部返回false
postProcessAfterInstantiation():return wrapIfNecessary(bean,beanName,cacheKey)
获取当前bean的所有增强器(通知方法)---切面类在初始化配置类@Bean中已创建
- 找到候选的所有增强器(找哪些通知方法是需要切入当前bean方法的)
- 获取到能在bean使用的增强器
如果当前bean需要增强,创建当前bean的代理对象
- 获取所有增强器(通知方法)
- 保存到proxyFactory
创建代理对象,Spring自动决定
- JdkDynamicAopProxy:jdk动态代理
- ObjectsysCglibAopProxy:cglib的动态代理
- 给容器中返回组件使用cglib增强了的代理对象
- 以后容器中获取到的就是这个组件的代理对象,执行目标方法的时候,代理对象就会执行通知方法的流程
代理对象目标方法执行:容器中保存了组件的代理对象(cglib增强后的对象),这个对象里面保存了详细信息(比如增强器,目标方法,目标对象等)
- CglibAopProxy.intercept():拦截目标方法的执行
根据ProxyFactory对象获取将要执行的目标方法拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method,targetClass);
- List<Object> interceptorList保存所有拦截器,一个默认的ExposeInvocationInterceptor和4个增强器
- 遍历所有的增强器,将其转换为Interceptor:registry.getInterceptor(advisor)
- 将增强器转为List<MethodInterceptor>,如果是MethodInterceptor,则直接加入到集合中,否则使用AdvisorAdapter将增强器转成MethodInterceptor
- 如果没有拦截器链,直接执行目标方法
- 如果有拦截器链,把需要执行的目标对象,目标方法,拦截器链等信息传入创建一个CglibMethodInvocation对象,并调用Object retval = cglibMethodInvocation.proceed()进行代理增强方法的调用.
拦截器链的触发过程
- 如果没有拦截器执行目标方法,或者拦截器的索引和拦截器数组-1
大小一样(指定到了最后一个拦截器)执行目标方法
- 链式获取每一个拦截器,拦截器执行invoke方法,每一个拦截器等待下一个拦截器执行完成以后再栏执行,拦截器链的机制,保证通知方法和目标方法的执行顺序
总结:
- @EnableAspectJAutoProxy:开启AOP功能
- @EnableAspectJAutoProxy:会给容器中注册一个组件AnnotationAwareAspectJAutoProxyCreator
- AnnotationAwareAspectJAutoProxyCreator是一个后置处理器
容器的创建流程
- registerBeanPostProcessors()注册后置处理器:创建AnnotationAwareAspectJAutoProxyCreator
finishBeanFactoryInitialization()初始化剩下的单实例bean
- 创建业务逻辑组件和切面组件
- AnnotationAwareAspectJAutoProxyCreator拦截组件的创建过程
组件创建完之后,判断组件是否需要增强
- 是:切面的通知方法,包装成增强器(Advisor),给业务逻辑组件创建一个代理对象
执行目标方法
- 代理对象执行目标方法
CglibAopProxy.intercept()
- 得到目标方法的拦截器链(增强器包装成拦截器MethodInterceptor)
- 利用拦截器的链机制,一次进入每一个拦截器进行执行
效果:
- 正常:前置通知=>目标方法=>后置通知=>返回通知
- 异常:前置通知=>目标方法=>后置通知=>异常通知
1.6 声明式事物
环境搭建:
- 导入相关依赖:数据源,数据库驱动,spring-jdbc模块
- 配置数据库,JdbcTemplate(Spring提供的简化数据库操作的工具)操作数据
- 给方法上标注@Transactional表示当前方法是一个事物方法
- @EnableTransactionManagement开启基于注解的事物管理功能---SpringBoot可以省略
- 配置事物管理器来控制事物,如:PlateformTransactionManager
事物原理:通过处理器对需要进行事物控制的实例化时创建代理对象存入容器
@EnableTransactionManagement
利用TransactionManagementConfigurationSelector给容器中会导入两个组件
- AutoProxyRegistrar
- ProxyTransactionManagementConfiguration
AutoProxyRegistrar
- 给容器中注册一个InfrastructureAdvisorAutoProxyCreator组件---是一个InstantiationAwareBeanPostProcessor实现类
- 利用BeanPostProcessor后置处理器机制,在对象创建后,包装对象,并返回一个代理对象(增强器),代理对象执行方法利用拦截器链进行
ProxyTransactionManagementConfiguration
给容器中注册事物增强器
- 事物增强器要用到事物注解的信息,AnnotationTransactionAttributeSource解析事物注解
事物拦截器
TransactionInterceptor:保存了事物属性信息,事物管理器---它是一个MethodInterceptor,在目标方法执行的时候,执行拦截器链
- 先获取事物相关的属性
- 再获取PlatformTransactionManager,如果事先没有添加指定任何TransactionManagement,那么最终会从容器中按照类型获取一个PlateformTransactionManagemer
执行目标方法:
- 如果异常:获取到事物管理器,利用事物管理回滚操作
- 如果正常,利用事物管理器,提交事物
1.7 扩展
1.7.1 BeanFactoryPostProcessor
BeanFactoryPostProcessor:来定制和修改BeanFactory的内容,如覆盖或添加属性
- BeanPostProcessor:Bean后置处理器,bean创建对象初始化前后进行拦截工作
- BeaFactoryPostProcessor:BeanFactory的后置处理器,在BeanFactory标准初始化之后调用,所有的bean定义已经保存加载到beanFactory,但是bean实例还未创建
BeanFactoryPostProcessor流程
- ico容器创建
invokeBeanFactoryPostProcessor(beanFactory):执行BeanFactoryPostProcessor
如何找到所有的BeanFactoryPostProcessor并执行他们的方法
- 直接在BeanFactory中找到所有类型是BeanFactoryPostProcessor的组件,并回调执行其postProcessBeanFactory()方法
- 在初始化创建其他组件前面执行
1.7.2 BeanDefinitionRegistryPostProcessor
BeanDefinitionRegistryPostProcessor
1. BeanDefinitionRegistryPostProcessor实现了BeanFactoryPostProcessor接口,是Spring框架的BeanDefinitionRegistry的后处理器,用来注册额外的BeanDefinition。postProcessBeanDefinitionRegistry方法会在所有的BeanDefinition已经被加载了,但是所有的Bean还没有被创建前调用 2. BeanDefinitionRegistryPostProcessor经常被用来注册BeanFactoryPostProcessor的BeanDefinition * Mybatis和spring整合时,我们通常会在application.xml中配置一个Bean,也就是MapperScannerConfigurer(该类实现了BeanDefinitionRegistryPostProcessor接口,所以支持动态注册mapper为Bean组件,并注入到spring容器中)。指定该Bean的包扫描路径属性。 3. BeanDefinitionRegistryPostProcessor执行流程 1. ioc创建对象 2. refresh()-----invokeBeanFactoryPostProcessors(beanFactory) 3. 从容器中获取到所有的BeanDefinitionRegistryPostProcessor组件的定义 1. 依次触发所有的BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry() 2. 再来触发BeanDefinitionRegistryPostProcessor#postProcessBeanFactory()
1.7.3 ApplicationListener
ApplicationListener:监听容器中发布的时间,事件驱动模型开发
流程
- 写一个监听器来监听某个事件(ApplicationEvent及其子类)
- 把监听器加入到容器
只要容器中有相关事件的发布,我们就能监听到这个事件
- ContextRefreshedEvent:容器刷新完成(所有的bean都完全创建)会发布这个事件
- ContextClosedEvent:关闭容器会发布这个事件
发布一个事件
- applicationContext.publishEevnet()
原理
事件派发器初始化
- 容器对象创建,refresh()
initApplicationEventMulticaster():初始化ApplicationEventMulticaster
- 先去容器中找有没有id="applicationEventMulticaster"组件
- 如果没有,则this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory),并加入到容器中,我们就可以在其他组件要派发事件时,自动注入这个applicationEventMulticaster
监听器初始化
- 容器对象创建,refresh()
registerListeners()
从容器中拿到所有的监听器Name,把他们注册到applicationEventMulticaster中
- String[] listenerBeanNames = getBeanNameForType(ApplicationListener.class,true,false)
- getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName)---注意:这里只是将监听器的BeanName注册到ApplicationEventMulticaster的ListenerRetriever中,其监听器的实例化是在ApplicationEventMulticaster#multicastEvent(event)时在ListenerRetriever中通过BeanName进行实例化的
ContextRefreshedEvent事件
- 容器对象创建#refresh()
- finishRefresh():容器刷新完成
publishEvent(new ContextRefreshedEvent(this))
事件发布流程:
- 获取事件的派发器:getApplicationEventMulticaster()
- multicastEvent派发事件
获取到所有的ApplicationListener---通过ListenerRetriever
- 如果有Executor.可以支持使用Executor进行异步派发
否则,同步的方式执行listener方法:invokeListener(listener,event)
- 通过listener回调onApplicationEvent方法
ContextClosedEvent事件
- 容器对象关闭ApplicationContext#close()
doClose()
- publishEvent(event):发布ContextClosedEvent
当监听器使用@EventListener
- 当使用@EventListener注解时,使用的是EventListenerMethodProcessor处理器afterSingletonsInstantiated()方法来解析方法上的@EventListener注解,此处理器创建一个拥有@EventListener的监听器到容器中
EventListenerMethodProcessor implements SmartInitializingSingleton
- 容器对象创建#refresh()
- finishBeanFactoryInitialization():完成BeanFactory初始化工作,创建剩下的Bean实例
- 在创建所有实例后,获取所有创建好的单实例bean,判断是否为SmartInitializingSingleton类型的,如果是就调用afterSingletonsInstantiated()方法来创建监听器
二.容器创建流程
2.1Spring容器的refresh()
2.1.1 prepareRefresh()
- 刷新前的预处理
- initPropertySources()初始化一些属性设置,子类自定义个性化的属性设置方法
- getEnvironment().validateRequiredProperties():检验属性的合法等
- earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>():保存容器中的一些早期的事件
2.1.2 obtainFreshBeanFactory()
- :获取BeanFactory
refreshBeanFactory():刷新创建BeanFactory
- 创建了一个this.beanFactory = new DefaultListableBeanFactory();
- 设置id
- scan配置文件和配置类,注册BeanName和BeanDefinition
- getBeanFactory():返回刚才GenericApplicationContext创建的BeanFactory对象
- 将创建的BeanFactory(DefaultListableBeanFactory)返回
2.1.3 prepareBeanFactory
- BeanFactory的预准备工作(BeanFactory进行一些设置)
- 设置BeanFactory的类加载器,支持表达式解析器...
- 添加部分BeanPostProcessor(ApplicationContextAwareProcessor)
设置忽略的自动装配的接口---不能自动注入
- EnvironmentAware
- EmbeddedValueResolverAware,
- ResourceLoaderAware,
- ApplicationEventPublisherAware,
- MessageSourceAware,
- ApplicationContextAware
设置可以自动装配的接口
- BeanFactory
- ResourceLoader
- ApplicationEventPublisher
- ApplicationContext
- 添加BeanPostProcessor(ApplicationListenerDetector)
- 添加编译时的AspectJ
给BeanFactory总注册一些能用的组件
- environment(ConfigurableEnvironment)
- systemProperties(Map<String,Object>)
- systemEnvironment(Map<String,Object>)
2.1.4 postProcessBeanFactory
- BeanFactory准备工作完成后进行的后置处理
- 子类通过重写这个方法来在BeanFactory创建并预准备完成以后做进一步的设置
=====================以上是BeanFactory的创建及预准备工作================
2.1.5 invokeBeanFactoryPostProcessors(beanFactory)
-
执行BeanFactoryPostProcessor的方法-----BeanFactoryPostProcessor:BeanFactory的后置处理器,在BeanFactory标准初始化之后执行,主要有两个接口:BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor
- 执行invokeBeanFactoryPostProcessors()方法
-
先获取所有的BeanDefinitionRegistryPostProcessor
- 执行实现PriorityOrderd优先级接口的BeanDefinitionRegistryPostProcessor#postProcessorBeanDefinitionRegistry(registry)
- 执行实现Ordered优先级接口的BeanDefinitionRegistryPostProcessor#postProcessorBeanDefinitionRegistry(registry)
- 最后执行没有实现任何优先级接口的BeanDefinitionRegistryPostProcessor#postProcesorBeanDefinitionRegistry(registry)
-
最后获取所有的BeanFactoryPostProcessor
- 执行实现PriorityOrdered优先级接口的BeanFactoryPostPrcessor#postProcessorBeanFactory
- 执行实现Ordered优先级接口的BeanFactoryPostProcessor#postProcessorBeanFactory
- 最后执行没有实现任何优先级接口的BeanFactoryPostProcessor#postProcessorBeanFactory
2.1.6 initMessageSource()
-
初始化MessageSource组件(国际化功能,消息绑定,消息解析)
- 获取BeanFactory
-
看容器中是否有id为messageSource的,类型为MessageSource的组件
-
如果有赋值给messageSource,如果没有就自己创建一个DelegatingMessageSource
- MessageSource:取出国际化配置文件中的某个key的值,能按照区域信息获取
-
-
把创建好的MessageSource注册在容器中,以后获取国际化配置文件的值时,可以自动注入MessageSource
- beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME,this.messageSource)
- MessageSource.getMessage(String code,Object[] args,String defaultMessage,Local local)
2.1.7 InitApplicationEventMulticaster()
-
初始化事件派发器
- 获取BeanFactory
- 从BeanFactory中获取applicationEventMulticaster的ApplicationEventMulticaster
- 如果上一步没有配置,则创建一个SimpleApplicationEventMulticaster
- 将创建的ApplicationEventMulticaster添加到BeanFactory中,以后其他组件直接自动注入
2.1.8 onRefresh()
-
留给子容器重写,同postProcessorBeanFactory()
子类重写这个方法,在容器刷新的时候可以自定义逻辑
2.1.9 registerListeners()
-
给容器中将所有项目里面的ApplicationListener注册进来
- 将容器的已有的ApplicationListener注册到ApplicationEventMulticaster
-
从容器中拿到所有的ApplicationListener定义Name注册到ApplicationEventMulticaster
- getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName)
-
派发之前步骤产生的事件
- getApplicationEventMulticaster().multicastEvent(earlyEvent);
- 注意:监听器的实例化是在发布事件后,在SimpleApplicationEventMulticaster#multicastEven()中通过ListenerRetriever实例化的,并根据Event类型存入缓存中retrieverCache中
2.1.10 finishBeanFactory
-
初始化所有剩下的单实例bean
-
beanFactory.preInstantiateSingletons():初始化后所有剩下的单实例bean
- 获取容器中的所有BeanNames,一次进行初始化和创建对象
- 获取Bean的定义信息:RootBeanDefinition
-
Bean非抽象的,非懒加载的,是单实例的
- 判断是否是FactoryBean,是否是实现FactoryBean的接口
-
不是工厂Bean,利用getBean(beanName):创建对象
- getBean(beanName):ioc.getBean()
- doGetBean(name,null,null,false)
-
先获取缓存中保存的单实例Bean,如果能获取到说明这个Bean之前被创建过(所有创建过的单实例Bean都会被缓存)
- private final Map<String,Object> singletonObjects = new ConcurrentHashMap<String,Object>();
- 缓存获取不到,开始Bean对象的创建流程
- 标记当前bean已经开始被创建
- 获取当前Bean依赖的其他Bean,如果有按照getBean()把依赖的Bean先创建出来
-
启动单实例Bean的创建流程
- createBean(beanName,mbd,args)
-
resolveBeforeInstantiation(beanName,mbdToUse)
-
让BeanPostProcessor先拦截返回代理对象---AOP
- 获取所有的InstantiationAwareBeanPostProcessor,如果存在则执行#postProcessBeforeInstantiation(),有返回值则继续执行postProcessorAfterInstantiation()
-
如果前面的InstantiationAwareBeanPostProcessr没有返回代理对象,则创建新的Bean实例
- Object beanInstance = doCreateBean(beanName,mbdToUser,args)
-
-
doCreateBean():创建Bean实例
-
创建一个空的Bean实例:createBeanInstance(beanName,mbd,args)
- 利用工厂方法或者对象的构造器方法创建出Bean实例
- applyMergedBeanDefinitionPostProcessor(mbd,beanType,beanName):执行MergedBeanDefinition后置处理器
-
populateBean(beanName,mbd,instanceWrapepr):Bean属性赋值
- 拿到InstantiationAwareBeanPostProcessor后置处理器,执行postProcessAfterInstantiation()
- 拿到InstantiationAwareBeanPostProcessor后置处理器,执行postProcessPropertyValues()
-
应用Bean属性的值:为属性利用setter方法进行赋值
- applyPropertyValues(beanName,mbd,bw,pvs)
-
Bean初始化:initializeValues(beanName,exposedObject,mbd)
- 执行Aware接口方法:invokeAwareMethods(beanName,bean):执行xxxAware接口,如:BeanNameAware,BeanClassLoaderAwaer,BeanFactoryAware
-
执行所有的后置处理器前置方法applyBeanPostProcessorsBeforeInitialization()
- BeanPostProcessor.postProcessorsBeforeInitialization()
-
执行初始化方法:invokeInitMethods(beanName,wrappedBean,mbd)
- 是否是InitializingBean接口的实现,执行接口规定的初始化方法
- 是否是自定义初始化方法
-
执行所有的后置处理器后置方法applyBeanPostProcessorAfterInitialization()
- BeanPostProcessor.postProcessAfterInitialization()
- 注册Bean的销毁方法
-
将创建的Bean添加到缓存中SingletonObjects:ioc容器就是这些Map,里面保存了单实例Bean,环境信息
- singletonObjects
- registeredSingletons
- 所有Bean都利用getBean创建完成以后,检查所有的Bean是否是SmartInitializingSingleton接口的实现,如果是,就执行afterSingletonsInstantiated--------@EventListener注解
-
-
2.1.11 finishRefresh()
- 完成BeanFactory的初始化创建,IOC容器就创建完成
initLifecycleProcessor():初始化和生命周期有关的后置处理器:LifecycleProcessor
- 默认从容器中找是否有lifecycleProcessor的组件(LifecycleProcessor),如果没有,则new DefaultLifectcleProcessor,并加入到容器中
我们也可以通过自己写一个LifecycleProcessor的实现类,
- void onRefresh();
- void onClose();
- getLifecycleProcessor().onRefresh(),拿到前面定义的生命周期处理器,回调onRefresh()
- liveBeanView.registerApplicationContext(this)
2.1.12 总结
Spring容器在启动的时候,先会保存所有注册进来的Bean的定义信息
- xml注册bean:<bean>
- 注解注册bean:@Component,@Bean,@Import
Spring容器会在适合的时机创建这些bean
- 用到这个bean的时候,利用getBean创建bean:创建好以后保存到容器中
- 通义创建剩下所有的bean'的时候:finishBeanFactoryInitialization()
后置处理器---BeanPostProcessor
- 每一个bean创建完成,都会使用各种后置处理器进行处理,来增强bean的功能
事件驱动模型
- ApplicationListener:事件监听
三.Web
3.1 servlet3.0
3.1.1 ServletContainerInitializer
Shared libraries(共享库) 和 runtimes pluggability(运行时插件能力)
- Servlet容器启动会扫描,当前应用里面每一个jar包的ServletContainerInitializer的实现,并通过@HandlerType注解传入感兴趣的类型
提供ServletContainerInitializer的实现类
- 必须绑定在:META-INF/services/javax.servlet.ServletContainerInitializer文件
- 文件的类容就是ServletContainerInitializer实现类的全类名
在ServletContainerInitializer#onstartup(Set<Class<?>> arg0,ServletContext sc)中通过ServletContext可以注册Servlet,Filter,Listener
- 而在传统的Servlet项目中,通常通过xml配置文件来注册映射到ServletContext中或者@Servlet,@Filter,@Listener注解(注解方式不适用于第三方组件)
3.1.2 SpringServletContainerInitializer
通过runtimes pluggability机制以注解的方式整合springMVC
- web容器在启动的时候,会扫描每个jar包下的META-INF/services/javax.servlet.ServletContainerInitializer
- 加载这个文件指定的类SpringServletContainerInitializer
- spring的应用一启动会通过@HandlerType注解加载感兴趣的WebApplicationInitializer接口下的所有组件
并且为WebApplicationInitializer组件创建对象(组件不是接口,不是抽象类)
- AbstractContextLoaderInitializer:创建根容器:createRootApplicationContext()
AbstractDispatcherServletInitializer
- 创建一个web的ioc容器:createServletApplicationContext()
- 创建了DispatcherServlet:createDispatcherServlet()
- 将创建的DsipatcherServlet添加到ServletContext中
AbstractAnnotationConfigDispatcherServletInitializer:注解方式配置的DispatcherServlet
创建根容器:createRootApplicationContext()
- getRootConfigClasses():传入一个配置类
创建web的ioc容器:createServletApplicationContext()
- 获取配置类:getServletConfigClasses()
- 总结:以注解方式启动SpringMVC:继承AbstractAnnotationConfigDispatcherServletInitializer实现抽象方法指定DsipatcherServlet的配置信息,而传统的SpringMVC则是通过配置文件,通过ContextLoaderListener来注册Root容器,通过DispatcherServlet来注册ioc容器
Public class MywebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer{ //获取跟容器的配置类:(Spring的配置文件) 父容器: @override protected Class<?>[] getRootConfigClasses(){ return new Class<?>[]{RootConfig.class}; } //获取web容器的配置类:(SpringMVC配置文件) 子容器: @override protected Class<?>[] getServletConfigClasses(){ return new Class<?>[]{AppConfig.class}; } //获取DispatcherServlet的映射信息 @override protected String[] getServletMappings(){ return new String[]{"/app1/*"}; } }
//Spring的容器不扫描controller:父容器 @ComponentScan(value="com.lsy",excludeFilters={@Filter(type=FilterType.ANNOTATION,classes={Controller.class}) }) public class RootConfig{ } //SpringMVC只扫描Controller:子容器 @ComponentScan(value="com.lsy",includeFilters={@Filter(type=FilterType.ANNOTATION,classes={Controller.class}) },useDefaultFilters=false) public class AppConfig{ }
3.1.3 WebMvcConfigurer
以上我们通过WebApplicationInitializer的实现AbstractAnnotationConfigDispatcherServletInitializer注册了DispatcherServlet,整合了MVC,接下来通过WebMvcConfigurer来实现添加其他的组件来定制化容器
以往我们定制化SpringMVC容器,可以通过springmvc.xml
<!--将SpringMVC处理不了的请求交给tomcat,静态资源就可以访问--> <mvc:default-servlet-handler/> <!--SpringMVC的高级功能开启--> <mvc:annotation-driven/> <!--添加拦截器--> <mvc:interceptors> ...... </mvc:interceptors> <!--添加视图解析器--> <mvc:view-controller path=""/>
现在通过JavaConfig的方式进行配置
- 之前已经通过SPI机制,在AbstractAnnotationConfigDispatcherServletInitializer的实现中注册父子容器的配置类,而我们需要在SpringMVC容器中添加组件,则可以通过在Application容器配置类中实现
- 我们通过配置类来实现WebMvcConfigurer接口来注册组件,由于java8接口中可以有默认方法,所以不需要使用之前的适配器WebMvcConfigurerAdapter类
//SpringMVC只扫描Controller:子容器 @ComponentScan(value="com.lsy",includeFilters={@Filter(type=FilterType.ANNOTATION,classes={Controller.class}) },useDefaultFilters=false) @EnableWebMvc public class AppConfig implements WebMvcConfigurer{ //试图解析器 @Override public void configureViewResolvers(ViewResolverRegistry registry){ //默认所有页面从/WEB-INFO/XXX.jsp register.jsp("/WEB-INF/views",".jsp") } //创建新试图解析器 @Bean public viewResolver viewResolver(){ InternalResourceViewResolver resolver = new InternalResourceViewResolver(); resolver.setPrefix("/WEB-INF.views"); resolver.setSuffix(".jsp"); return resolver; } //静态资源访问 @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer){ configurer.enable(); } //拦截器 @Override public void addInterceptors(InterceptorRegistry registry){ registry.addInterceptor(new MyFirstInterceptor()).addPathPatterns("/**"); } }
3.1.4 SpringBoot中的MVC
@EnableAutoConfiguration
- 在SpringBoot通过@EnableAutoConfiguration来启动整个应用,此注解Import AutoConfigurationImportSelector选择器,此选择器会去读取META-INFO/spring.factories文件,其中通过WebMvcAutoConfiguration来注册MVC中DispatcherServlet和其他组件
WebMvcAutoConfiguration
- 此配置类上有一系列Conditional注解
- @AutoConfigureAfter({DispatcherServletAutoConfiguration.class, ValidationAutoConfiguration.class}),所有此注解会注册DispathcerServlet
- EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport:此类相当于@EnableWebMvc,注册DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport 用来注册其他组件
当需要在SpringBoot中自定义组件时,有三种配置方式
@EnableWebMvc + extends WebMvcConfigurerAdapter:在扩展的类中重写父类的方法即可,这种方式会屏蔽SpringBoot的@EnableAutoConfiguration中的设置
- 由于使用@EnableWebMvc,此注解会Import DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport,而在@EnableAutoConfiguration import WebMvcAutoConfiguration中有@ConditionalOnMissingBean({WebMvcConfigurationSupport.class}),所以SpringBoot的自动配置会失效
extends WebMvcConfigurationSupport:在扩展的类中重写父类的方法即可,这种方式会屏蔽SpringBoot的@EnableAutoConfiguration中的设置
- 当注册WebMvcConfigurationSupport的子类时,在@EnableAutoConfiguration import WebMvcAutoConfiguration中@ConditionalOnMissingBean({WebMvcConfigurationSupport.class}),所以SpringBoot的自动配置会失效
- extends WebMvcConfigurerAdapter:在扩展的类中重写父类的方法即可,这种方式依旧使用SpringBoot中的@EnableAutoConfiguration中的设置
implements WebMvcConfigurer:java8接口引入默认方法,在扩展的类中重写接口的方法即可,这种方式依旧使用SpringBoot中的@EnableAutoConfiguration中的设置-----推荐方式
- SpringBoot会将WebMvcConfigurer的实现和其组件注册到容器中
- 而Spring注解整合MVC中,通过读取WebMvcConfigurer配置类来创建MVC容器,并把配置类中组件注册到容器中
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。