作者:COLDE 文章內(nèi)容輸出來源:拉勾教育Java高薪訓(xùn)練營(yíng)課程
-
IOC概述
1.1 什么是IOC
控制反轉(zhuǎn)(Inversion of Control,縮寫為IoC),是面向?qū)ο缶幊讨械囊环N設(shè)計(jì)原則,可以用來減低計(jì)算機(jī)代碼之間的耦合度。其中最常見的方式叫做依賴注入(Dependency Injection,簡(jiǎn)稱DI),還有一種方式叫“依賴查找”(Dependency Lookup)。通過控制反轉(zhuǎn),對(duì)象在被創(chuàng)建的時(shí)候,由一個(gè)調(diào)控系統(tǒng)內(nèi)所有對(duì)象的外界實(shí)體將其所依賴的對(duì)象的引用傳遞給它。也可以說,依賴被注入到對(duì)象中。
傳統(tǒng)開發(fā)模式

IoC模式

1.2 IOC解決了什么問題

-
OOP開發(fā)模式
UserService和UserDao深度耦合,當(dāng)UserDao發(fā)生變更時(shí),會(huì)聯(lián)動(dòng)引發(fā)UserService的變更,高層模塊依賴于底層模塊,違法依賴倒置原則。
-
IOP開發(fā)模式
將UserDao抽象為IUserDao接口,UserService依賴于IUserDao抽象接口,不依賴其具體實(shí)現(xiàn),但在創(chuàng)建IUserDao實(shí)例對(duì)象時(shí)(new UserDaoImpl),UserService還是依賴其實(shí)例對(duì)象。
-
IoC開發(fā)模式
對(duì)象之間只依賴于抽象規(guī)則,不依賴其具體實(shí)現(xiàn),具體實(shí)例的創(chuàng)建權(quán)限交由IOC容器進(jìn)行控制,極大的降低代碼的耦合度
2. Spring IoC深入分析
IoC容器是Spring的核心模塊,是抽象了對(duì)象管理、依賴關(guān)系管理的框架解決方案。BeanFactory為頂層容器,不能被實(shí)例化,它定義了所有IoC容器必須遵從的一套原則,具體的容器實(shí)現(xiàn)可以增加額外的功能。以Spring Boot默認(rèn)加載容器AnnotationConfigApplicationContext為例,其繼承體系如下:

其中GenericApplicationContext持有一個(gè)BeanFactory的默認(rèn)實(shí)現(xiàn)類DefaultListableBeanFactory的實(shí)例對(duì)象,Spring Context使用代理模式使用該實(shí)例替它執(zhí)行BeanFactory接口定義的功能。DefaultListableBeanFactory繼承體系如下:

源碼分析
- 源碼分析用例
public class AnnotationConfigApplicationContextTest {
// 聲明配置Bean
@Configuration
public class BeanConfiguration {
@Bean
public TestBean getTestBean(){
return new TestBean();
}
}
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanConfiguration.class);
TestBean bean = applicationContext.getBean(TestBean.class);
System.out.println(bean);
}
}
- Spring上下文容器初始化
public class GenericApplicationContext{
public GenericApplicationContext() {
// 創(chuàng)建BeanFactory的默認(rèn)容器實(shí)現(xiàn)類,有關(guān)BeanFacory相關(guān)的大部分功能通過代理模式使用該實(shí)例進(jìn)行實(shí)現(xiàn)
this.beanFactory = new DefaultListableBeanFactory();
}
}
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {
private final AnnotatedBeanDefinitionReader reader;
private final ClassPathBeanDefinitionScanner scanner;
public AnnotationConfigApplicationContext() {
// 配置Bean處理器
this.reader = new AnnotatedBeanDefinitionReader(this);
// 包掃描處理器
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
// 注解方式上下文創(chuàng)建入口
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
// 重載構(gòu)造方法,創(chuàng)建reader、scanner,調(diào)用父類構(gòu)造方法創(chuàng)建DefaultListableBeanFactory的實(shí)例對(duì)象
this();
// 注冊(cè)配置bean
register(componentClasses);
// 容器初始化核心方法
refresh();
}
public void register(Class<?>... componentClasses) {
this.reader.register(componentClasses);
}
public void scan(String... basePackages) {
this.scanner.scan(basePackages);
}
}
- register:注冊(cè)配置Bean
public class AnnotatedBeanDefinitionReader {
// 注冊(cè)bean入口
public void register(Class<?>... componentClasses) {
for (Class<?> componentClass : componentClasses) {
registerBean(componentClass);
}
}
public void registerBean(Class<?> beanClass) {
doRegisterBean(beanClass, null, null, null, null);
}
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
@Nullable BeanDefinitionCustomizer[] customizers) {
// 包裝為BeanDefinition對(duì)象
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
// 設(shè)置創(chuàng)建bean對(duì)象時(shí)的鉤子方法
abd.setInstanceSupplier(supplier);
// 獲取bean的Scope屬性
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
// 獲取beanName
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
// 處理bean上的注解
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
// 源碼略...
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
//調(diào)用BeanDefinitionReaderUtils.registerBeanDefinition
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
}
public abstract class BeanDefinitionReaderUtils {
}
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) {
//beanName注冊(cè)
String beanName = definitionHolder.getBeanName();
// 調(diào)用DefaultListableBeanFactory的registerBeanDefinition方法
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
//別名注冊(cè)
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
public class DefaultListableBeanFactory{
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
private volatile List<String> beanDefinitionNames = new ArrayList<>(256);
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition){
// 其他邏輯代碼略
// 將bean信息包裝類放置到beanDefinitionMap中
// 至此,bean注冊(cè)邏輯完成
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
}
}
- refresh:容器初始化核心邏輯分析
public class AbstractApplicationContext {
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 1、預(yù)處理設(shè)置啟動(dòng)時(shí)間活動(dòng)標(biāo)記
prepareRefresh();
// 2、獲取BeanFactory;默認(rèn)實(shí)現(xiàn)是DefaultListableBeanFactory,由GenericApplicationContext構(gòu)造方法中創(chuàng)建
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 3、BeanFactory的預(yù)準(zhǔn)備?作
prepareBeanFactory(beanFactory);
try {
// 4、BeanFactory準(zhǔn)備?作完成后進(jìn)?的后置處理?作
postProcessBeanFactory(beanFactory);
// 5.1、實(shí)例化并調(diào)?實(shí)現(xiàn)了BeanFactoryPostProcessor接?的Bean
// 5.2、解析配置類中Bean信息并注冊(cè)
invokeBeanFactoryPostProcessors(beanFactory);
// 6、注冊(cè)BeanPostProcessor(Bean的后置處理器)
registerBeanPostProcessors(beanFactory);
// 7、初始化MessageSource組件(做國(guó)際化功能;消息綁定,消息解析)
initMessageSource();
// 8、初始化事件派發(fā)器
initApplicationEventMulticaster();
// 9、鉤子方法,?類重寫這個(gè)?法,在容器刷新的時(shí)候可以?定義邏輯
onRefresh();
// 10、注冊(cè)應(yīng)?的監(jiān)聽器。就是注冊(cè)實(shí)現(xiàn)了ApplicationListener接?的監(jiān)聽器bean
registerListeners();
// 11、初始化所有剩下的?懶加載的單例bean
finishBeanFactoryInitialization(beanFactory);
// 12、完成context的刷新。主要是調(diào)?LifecycleProcessor的onRefresh()?法,并且發(fā)布事件
finishRefresh();
}
catch (BeansException ex) { }
}
}
}
- 解析配置類中的Bean信息并注冊(cè)
// 核心代碼
class ConfigurationClassBeanDefinitionReader {
private void loadBeanDefinitionsForConfigurationClass(
ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
// 解析配置類中的bean配置方法
loadBeanDefinitionsForBeanMethod(beanMethod);
// 最終調(diào)用DefaultListableBeanFactory的registerBeanDefinition進(jìn)行bean的注冊(cè)
this.registry.registerBeanDefinition(beanName, beanDefToRegister);
}
}
}
- 循環(huán)依賴對(duì)象創(chuàng)建分析
//開始初始化Bean
DefaultListableBeanFactory#preInstantiateSingletons
AbstractBeanFactory#getBean
AbstractBeanFactory#doGetBean
// #從三級(jí)緩存中獲取Bean,解決循環(huán)依賴關(guān)鍵位置,第一次返回null
DefaultSingletonBeanRegistry#getSingleton
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 從一級(jí)緩存獲取,獲取成功則對(duì)象已經(jīng)創(chuàng)建成功
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
// 從二級(jí)緩存取
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 從三級(jí)緩存取,獲取成功則從三件緩存**剪切**對(duì)象到二級(jí)緩存
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
// 創(chuàng)建實(shí)例bean,還未對(duì)實(shí)例bean對(duì)象屬性進(jìn)行賦值
AbstractAutowireCapableBeanFactory#doCreateBean
AbstractAutowireCapableBeanFactory#createBeanInstance
// 將實(shí)例bean包裝未ObjectFactory對(duì)象,放入三級(jí)緩存提前暴露對(duì)象 DefaultSingletonBeanRegistry#addSingletonFactory(ObjectFactory)
// 屬性填充
AbstractAutowireCapableBeanFactory#populateBean
AbstractAutowireCapableBeanFactory#autowire*
AbstractBeanFactory#getBean
AbstractBeanFactory#doGetBean
// 繼續(xù)嘗試從三級(jí)緩存中獲取對(duì)象,如獲取失敗,執(zhí)行bean創(chuàng)建邏輯,并放入緩存供依賴對(duì)象獲取填充
DefaultSingletonBeanRegistry#getSingleton
-
循環(huán)依賴流程說明
Spring-IOC-循環(huán)依賴.png
總結(jié)
Spring IoC將對(duì)象的創(chuàng)建權(quán)限和對(duì)象之間的依賴關(guān)系交由容器進(jìn)行管理,使得代碼之間的耦合度進(jìn)一步降低,業(yè)務(wù)開發(fā)時(shí),一旦對(duì)象之間的抽象關(guān)系確立,底層業(yè)務(wù)邏輯發(fā)生業(yè)務(wù)變更,無(wú)需修改上層邏輯即可實(shí)現(xiàn)業(yè)務(wù)的變更,達(dá)到對(duì)象之間只依賴與抽象而不依賴于具體實(shí)現(xiàn)。
