spring和springioc源码解析

spring体系结构特别繁琐,其中最核心的就是ioc和aop。

首先了解如何基于注解启动spring容器。

注解方式环境搭建

@Configuration

使用Configuration 配置容器

@Configuration
public class MySpringConfig {
   
//@Configuration 等同于配置的spring配置文件
   
@Bean
   
public UserEntity userEntity() {
       
return new UserEntity(10, "cx");
    }
}

 

public class UserEntity {
   
private Integer userId;
   
private String userName;

   
public UserEntity(Integer userId, String userName) {
       
this.userId = userId;
       
this.userName = userName;
    }

   
public Integer getUserId() {
       
return userId;
    }

   
public String getUserName() {
       
return userName;
    }

   
public void setUserId(Integer userId) {
       
this.userId = userId;
    }

   
public void setUserName(String userName) {
        
this.userName = userName;
    }
}

使用注解形式形式加载IOC

private static AnnotationConfigApplicationContext applicationContext;

public static void main(String[] args) {
   
applicationContext = new AnnotationConfigApplicationContext(MySpringConfig.class);
    UserEntity userEntity =
applicationContext.getBean("userEntity", UserEntity.class);
    System.
out.println(userEntity.toString());
}

AnnotationConfigApplicationContext是继承于ApplicationContext,专门为注解方式的spring上下文加载控制器。spring boot就是用的这个控制器实现的。

比较老旧的读取xml的ApplicationContextClassPathXmlApplicationContext

 

先来看看new AnnotationConfigApplicationContext(MySpringConfig.class);的内部调用

https://img-blog.csdnimg.cn/20190707150206964.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzI4MDU2NTcx,size_16,color_FFFFFF,t_70 ​ ​ ​

最后会走入

AnnotatedBeanDefinitionReader.doRegisterBean方法

https://img-blog.csdnimg.cn/201907071533547.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzI4MDU2NTcx,size_16,color_FFFFFF,t_70 ​ ​

BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);方法我们来看看

https://img-blog.csdnimg.cn/2019070715335437.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzI4MDU2NTcx,size_16,color_FFFFFF,t_70 ​ ​方法调用者的this.registry是啥呢?

方法调用者的构造方法

https://img-blog.csdnimg.cn/20190707153512388.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzI4MDU2NTcx,size_16,color_FFFFFF,t_70 ​ ​

发现没有 这个 ​this.registry就是AnnotationConfigApplicationContext

https://img-blog.csdnimg.cn/20190707153601211.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzI4MDU2NTcx,size_16,color_FFFFFF,t_70

 

 

 

AnnotationConfigApplicationContext的父级GenericApplicationContext就实现了registerBeanDefinition方法,又调用了内部的beanfactory

            

https://img-blog.csdnimg.cn/20190707154140497.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzI4MDU2NTcx,size_16,color_FFFFFF,t_70

Beanfactory对象是DefaultListableBeanFactory

https://img-blog.csdnimg.cn/20190707154140549.png

让我们看看DefaultListableBeanFactory,发现这个就是真正的beanfactory容器!!里面的

beanDefinitionMap就是专门根据id储存bean对象的

https://img-blog.csdnimg.cn/20190707154239133.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzI4MDU2NTcx,size_16,color_FFFFFF,t_70

这样一来spring的配置信息终于读取完成,并且注册到bean容器了。

 

接下来看其他的bean是怎么注册的吧

查看

public AnnotationConfigApplicationContext(Class... annotatedClasses) {
    this();
    this.register(annotatedClasses);
    this.refresh();
}

的refresh方法

refresh又调用了finishBeanFactoryInitialization,继续调用的preInstantiateSingletons方法.再继续调用getbean继续一个劲的往下找  最后终于找到生成bean的地点  docreatebean  。

根据方法名可以才看出来是会初始化非懒加载的,并且作用域是单例的bean对象。

继续往下之前 我们需要了解一下BeanPostProcessor,Aware和InitializingBean接口。

AWARE接口是属于获取bean上下文的一种接口 ,具体实现类有很多,比如ApplicationContextAware,beanfactoryaware,他会在执行完构造函数之后执行

BeanPostProcessor接口是前置后置处理器,主要作用是再初始化bean的时候,环绕bean的初始化方法(不是构造方法,bean在走完钩爪方法后还会有一个bean初始化方法,这个方法需要开发人员根据业务需求去编写,如果没有这个需求,就不会有bean初始化方法)。

想要编写bean初始化方法 需要继承InitializingBean接口

代码示例  代码执行顺序是重上往下

这个时候是不是瞬间发现了bean的生命周期

spring的生命周期就是 

-》构造方法

-》反向注入需要的bean对象

-》执行aware (这里需要注意,很多aware也是基于BeanPostProcessor实现的方法调用的,所以他也可能处于bean初始化的前置环绕或者后置环绕)

-》执行bean初始化前置环绕(ApplicationContextAware就是通过前置处理器实现的)

-》执行bean初始化方法

-》执行bean初始化后置环绕(aop的动态代理就是在这儿实现的,aop就是后置处理器的aware实现的)

-》bean销毁

我们了解这些后 我们继续看看源码的AbstractAutowireCapableBeanFactory下的docreatebean方法

进入initializeBean方法

继续深入invokeAwareMethods就可以看到只有BeanNameAware,BeanClassLoaderAware和BeanFactoryAware这几个Aware

是在这儿执行的。说明其他的aware都是基于BeanPostProcessor实现的

嗯 springioc源码基本到这儿就讲解完了 ,在这儿补充一个流程图

发布了19 篇原创文章 · 获赞 11 · 访问量 3079

猜你喜欢

转载自blog.csdn.net/qq_28056571/article/details/94989875