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://i-blog.csdnimg.cn/blog_migrate/7ee63f9cec4176b588e5c30e8a9de6bd.png ​ ​ ​

最后会走入

AnnotatedBeanDefinitionReader.doRegisterBean方法

https://i-blog.csdnimg.cn/blog_migrate/77f7a934ef000d70e028d8530c9cef82.png ​ ​

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

https://i-blog.csdnimg.cn/blog_migrate/0c8e431dfe1285f68e0a05bea848342d.png ​ ​方法调用者的this.registry是啥呢?

方法调用者的构造方法

https://i-blog.csdnimg.cn/blog_migrate/a9928cf0c2ab8d78f26a415f073faf5f.png ​ ​

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

https://i-blog.csdnimg.cn/blog_migrate/29c7d4b0968eb63a65352157b5576c10.png

 

 

 

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

            

https://i-blog.csdnimg.cn/blog_migrate/982594685602fba7d552a44276a30bbf.png

Beanfactory对象是DefaultListableBeanFactory

https://i-blog.csdnimg.cn/blog_migrate/c2987233c2159cda1eb8f9d804383538.png

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

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

https://i-blog.csdnimg.cn/blog_migrate/3f538be18ab9887d133d55821bb17eb4.png

这样一来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源码基本到这儿就讲解完了 ,在这儿补充一个流程图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值