spring的生命周期(IOC+DI)
2021-07-16 14:38:24 0 举报
spring生命周期
作者其他创作
大纲/内容
再来一次判断实现没实现Ordered接口最后是没有实现任何排序接口的调用之后对BeanFactoryPostProcessor的来一遍加载
singletonsCurrentlyInCreation正在创建的bean集合对于循环依赖的解决很有帮助。会直接抛出构造函数的循环依赖异常
尝试从缓存获取
ApplicationContextAwareProcessorinvokeAwareInterfaces(Object bean)判断了一堆Aware的调用实现
finishBeanFactoryInitialization()前面折腾了一堆。这个是spring实例化最重要的方法
xml的解析在定义标签解析ComponentScan标签的时候进行了BeanPostProcessor的支持
创建@ComponentScan @Configuration支持类的支持new ConfigurationClassParser(...)
NamespaceHandlerSupport中的parse
根据类型判断选择调用AutowiredFieldElementAutowiredMethodElement
1.创建了BeanFactory(DefaultListableBeanFactory)2.xml解析(传统标签的解析,自定义标签的解析)3.把解析出来的xml对象进行了BeanDefinition对象的封装
CommonAnnotationBeanPostProcessor这个子类的实现分成两步,1.交给父类收集@PostConstruct,@PreDestroy
完成对实现下面两个接口的类的调用操作。目的是提供修改BeanDefinition对象的方法BeanDefinitionRegistryPostProcessor,BeanFactoryPostProcessor
这里调用的是ConfigurationClassPostProcessor的这个方法,之后调用processConfigBeanDefinitions(registry)
delegate.parseBeanDefinitionElement(ele);解析document,封装成BeanDefinition
调用parse,parse。。ComponentScanAnnotationParser的parse方法执行了 scanner.doScan方法从而完成这个路径下的包的扫描操作
这里就是对AutoWired中获取参数实例的方法里面调用的是getBean有参函数会掉到这里参数的依赖注入也会到这里方法的依赖注入也会到这里
建立别名和 id的映射,这样就可以根据别名获取到id(基本没用)
InitDestroyAnnotationBeanPostProcessor获取metadata findLifecycleMetadata(bean.getClass());
既然是埋点就是for循环所有的BeanPostProcessor让他们的子类进行收集装配
创建一个ScannedGenericBeanDefinition()对象并赋值beanClassName,之后加入存放bean的set集合中
在创建DisposableBeanAdapter的时候1.获取destory-method属性span style=\"font-size: inherit;\
循环一次beanFactoryPostProcessors==》这里只关注和BeanDefinitionRegistryPostProcessor有关的(没拿到东西)
检查bean是否重复
org.springframework.context.annotation.internalConfigurationAnnotationProcessororg.springframework.context.annotation.internalAutowiredAnnotationProcessororg.springframework.context.annotation.internalCommonAnnotationProcessororg.springframework.context.event.internalEventListenerProcessororg.springframework.context.event.internalEventListenerFactory增加这五个beanPostProcessor的支持(也会以beandefinition形式进行一个注册)
obtainFreshBeanFactory();
CommonAnnotationBeanPostProcessor
beanFactory.getBean(beanName)
获取之前注册的BeanDefinition的names集合开始循环获取BeanDefinition对象
List<LifecycleElement> initMethods = new ArrayList<>(); List<LifecycleElement> destroyMethods = new ArrayList<>();LifecycleMetadata
进行了一堆有的没的操作之后把beanDefinition放到map中
1、bean实例化过程 2、ioc 3、注解支持 4、BeanPostProcessor的执行 5、Aop的入口
1.判断BeanFactory是否为空,如果不是清空2.创建实例工厂。写入id,设置(是否循环依赖。是否可以重名的两个属性)3.开始解析xml,并封装成BeanDefinition(特别绕)
beforeSingletonCreation(beanName);在这个集合里面的bean都是正在实例化的bean
上一步完成里BeanDefinitionHolder对象的创建之后使用SPI思想获取MEAT-INF下的spring.handlers获取处理类,并用装饰器模式对holder对象进行子属性装饰(这里的不重要,自定义标签的这里重要。方式是一样的)
loadBeanDefinitions(Resource resource)包装了一层变成EncoderdResource
scanCandidateComponents(basePackage);
其他有的没的属性
不是FactoryBean的直接返回是的继续。先从缓存获取
refresh();
buildAutowiringMetadata(clazz);创建完成后加入缓存
methodOverrides
1. refreshBeanFactory();
alias标签解析
InputSource inputSource = new InputSource(inputStream);jdk的xml文件解析对象
buildLifecycleMetadata(clazz)创建完成后加入缓存
ImportAwareBeanPostProcessor 对ImportAware类型实例setImportMetadata调用(还不懂)
在实例化和 IOC/DI 做完后,就会调用 FactoryBean 类型的接口,如果要获取到 FactoryBean 类本身,就必须加上”&”符号,比如 beanFactory.getBean(\"&beanName\")factoryBeanObjectCache单独的缓存
大多数普通类直接调用\tgetBean(beanName);
是aop的入口
这里需要注意的是 createReaderContext(resource)这里完成了XmlBeanDefinitionReader封装
同时满足(不是抽象的,单例的。非懒加载的)条件会进行实例化操作
getSingleton(beanName);涉及循环依赖不做展开
spring初始化的核心方法
循环判断实现没实现PriorityOrdered实现了的话就加入一个集合。之后进行invoke调用
上面对象也创建了。备胎也都找到创建关系了我们还少一部分没整。就是初始化调用的一批方法
Method的inject
delegate.parseCustomElement(ele);自定义标签解析
【BeanPostProcessor的埋点应用之一】这里没有做注解限制。但是很多processor没有特殊实现单纯的返回beanApplicationContextAwareProcessorInitDestroyAnnotationBeanPostProcessorImportAwareBeanPostProcessor
没有
判断bean是否实现了FactoryBean接口,实现了进行一次&前缀初始化,一次本类实例化isFactoryBean(beanName)
getResourcePatternResolver().getResources(packageSearchPath);这里是递归获取文件所有包下文件
BeanNameAwareBeanClassLoaderAwareBeanFactoryAware
循环所有刚刚封装到的beandefinition
这里对@Import注解和@ImportSource等注解的解析没有体现。具体的分为两步。一步是扫描到了这些注解。之后是调用了loadDefinition()进行了一个注册
afterSingletonCreation(beanName);bean创建完成后singletonsCurrentlyInCreation要删除该bean
扫描并把扫描的类封装成beanDefinition对象 scanner.doScan(basePackages);
1.从MATE-INF/下的spring.handlers获取URI 对应的handlerthis.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
import标签解析
调用子类ResourceElement的getResourceToInject()方法
这里用这标签举例context:component-scan
1.把inputSource 封装成Document文件对象
prepareBeanFactory(beanFactory)给bean工厂设置一些属性
1.调用FactoryMethod的实例化2.有参构造的实例化3.无参构造实例化
DefaultListableBeanFactorybeanFactory.preInstantiateSingletons();具体的实例化过程
从xml解析等环节获取beanNames集合。之后开始遍历
bean标签的解析
loadBeanDefinitions(reader)委托给了reader
@PostConstruct注解和afterPropertiesSet和Init-method的方法其实核心功能都是一样的,只是调用时序不一样而已,都是在该类实例化和 IOC 做完后调用 的,我们可以在这些方法中做一些在 spring 或者 servlet 容器启动的时候的初始化 工作。
Filed的inject
getMetadataReaderFactory().getMetadataReader(resource);包装了类的基本信息的对象(metadataReader)
AutowiredAnnotationBeanPostProcessor
beanDefinitionMap这个map使用kv存储名字和对象beanDefinitionNames 这个list存名称
registerBeanPostProcessors(beanFactory)把实现了BeanPostProcessor接口的类实例化,并且加入到BeanFactory中
调用对应处理类的parse方法handler.parse()不同的子类会进行不同的解析操作。最后都会返回BeanDefinition对象
Resource[] resources对象的封装getResources(location);
DefaultNamespaceHandlerResolver.resolve()完成获取handler全类名。使用反射实例化
buildResourceMetadata(clazz);创建完成后加入缓存
\tfinishRefresh();最后事件发布
AbstractXmlApplicationContext.loadBeanDefinitions(beanFactory)系列方法包括期间使用委托模式的跳转
国际化 initMessageSource();初始化事件管理类initApplicationEventMulticaster();往事件管理类中注册事件类 registerListeners();
2. getBeanFactory();
invokeBeanFactoryPostProcessors(beanFactory)对beanDefinition进行了一个增删改查
resolveScopeMetadata()获取bean的scope属性
findCandidateComponents(basePackage);递归扫描文件获取所有注解类并封装beanDefinition
singletonFactory.getObject();调外层实现
再判断是Field还是method分别调用不同的反射方法
经过了甩锅操作转换了干活的人doRegisterBeanDefinitions(doc.getDocumentElement());
InitDestroyAnnotationBeanPostProcessor(替儿子收集步骤一的注解)findLifecycleMetadata(clazz)先看缓存。没有就去扫描
postProcessBeanDefinition()设置更多的属性processCommonDefinitionAnnotations提供注解支持创建BeanDefinitionHolder获取一个代理(不确定)完成bean的注册完成了扫描操作
loadBeanDefinitions(resources);方法内循环调用解析单个resource模板模式调到子类实现XmlBeanDefinitionReader
constructorArgumentValues用来存储配置的构成函数参数
1.获取namespaceUri getNamespaceURI(ele);
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();InjectionMetadata
setConfigLocations(configLocations);写入了要读取的文件。并设置给了AbstractRefreshableConfigApplicationContext
【BeanPostProcessor的埋点应用之一】关注有实现InstantiationAwareBeanPostProcessor接口的处理器
调用ComponentScanBeanDefinitionParserparse()
for循环中,进行父子bean的合并。用父类创建容器,之后用子类属性覆盖 getMergedLocalBeanDefinition(beanName);
0 条评论
下一页