IOC角色
ioc是spring中最最最最核心的内容,之所以打这么多最,是因为ioc是spring的底层支撑组件,后面讲述的
AOP、事务、和其他框架集成spring均是基于ioc去实现的。
IOC是什么
IOC-全拼Inversion of Control,翻译过来叫控制反转。在没有IOC的情况下,我们创建对象是需要手动去
new对象,解耦比较复杂,IOC理论提出的观点大体是这样的:借助于“第三方”实现具有依赖关系的对象之间
的解耦,IOC实现了以下三点:
1.资源不由使用资源的双方管理,而由不使用资源的第三方管理
2.资源集中管理,实现资源的可配置和易管理
3.降低了使用资源双方的依赖程度-耦合度
IOC加载流程
那么IOC到底是怎么实现的?大概分为以下几个主流程,主流程中一些比较重要的流程会在后面给出,本节
只讲主流程,干货开始。
1.xml、注解配置bean
文章源码以注解方式为例,如@Bean、@Component
2.ClassPathXmlApplicationContext和AnnotationConfigContext加载1配置
(1)以注解AnnotationConfigContext为例,这个类作为源码阅读的总入口,首先初始化context,初始化父类beanFactory image.png
public class ApplicationStart {
@SuppressWarnings("resource")
public static void main(String[] args) {
AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext(MainConfig.class);
Car bean = (Car)context.getBean("car");
System.out.println(bean.getName());
}
}
Mainconfig代码
@Configuration
@ComponentScan(basePackages = {"com.wubanf.friends.test.spring"})
@EnableTransactionManagement
public class MainConfig {
}
我们来看看AnnotationConfigApplicationContext的构造方法,这里有三个核心的大方法:
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
this();
//注册配置类
register(annotatedClasses);
//IOC容器刷新
refresh();
}
1.其中this会初始化化两个类,分别是AnnotatedBeanDefinitionReader-注解模式下bean定义扫描器和ClassPathBeanDefinitionScanner-classPath类型的bean定义扫描器,这里会初始化很多spring内置bean后置处理器(后置处理器的作用将在后面章节给出),spring体系中,实例化bean是需要先将bean转成bean定义,然后才能交给bean工厂实例化,bean定义就好比是工厂的加工原材料。
2.register会加载我们的配置类,如我上面自己定义的MainConfig类,通过自定义配置扫描的包,会自动扫描该包的bean,并且装载成bean定义,放入beanDefinitionMap中,后面供bean工厂使用
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
3.refresh-ioc容器刷新接口,真正实例化的步骤均在里面
3.refresh()--ioc容器刷新
这个是ioc实例化bean的核心方法入口,代码如下,其中核心是invokeBeanFactoryPostProcessors、registerBeanPostProcessors、finishBeanFactoryInitialization这三个方法
prepareRefresh();
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
prepareBeanFactory(beanFactory);
try {
postProcessBeanFactory(beanFactory);
// 调用我们的bean工厂的后置处理器.
invokeBeanFactoryPostProcessors(beanFactory);
// 调用我们bean的后置处理器
registerBeanPostProcessors(beanFactory);
initMessageSource();
initApplicationEventMulticaster();
onRefresh();
registerListeners();
//实例化bean.
finishBeanFactoryInitialization(beanFactory);
finishRefresh();
4.finishBeanFactoryInitialization-实例化我们剩余的单实例bean
实例化bean,这里主要分为三个步骤,方法入口beanFactory.getBean->AbstractBeanFactory.doGetBean->createBean->doCreateBean
1.反射实例化对象,createInstance
2.填充属性,populate @Autowired,@Value
3.初始化方法,initializeBean
总结
该节讲述了spring加载bean的大体流程,配置->初始化beanDefinitionReader->实例化spring内置后置处理器->加载配置类->加载bean定义->bean工程实例化bean。
初次阅读源码的时候忌一头栽进源码debug,spring的源码调用链很复杂,很容易迷失方向,先了解原理和主体流程会事半功倍,后面的流程细节慢慢发
网友评论