spring源码解析-1.初体验

Spring源码理解

首先两个概念:ioc和aop

1.IOC

ioc其实就是一个对象容器,可以进行控制反转和依赖注入,ioc容器里就是很多不一样的bean对象,本质就是java的普通对象,是用反射的方式创建出来的对象。
在这里插入图片描述

bean对象如何创建出来的?
1、接口beanDefinitionReader通过读取BeanDefinition(xml文件或者注解的方式,不同读取方式有不一样的beanDefinitionReader实现类),将bean对象的定义信息(也就是BeanDefinition,这个对象可以进行扩展,实现我们需要的功能)在ioc容器中实例化(反射的方式)对象,除此之外,读取xml或者注解的信息,我们必须先把BeanFactory创建出来
在这里插入图片描述

2、BeanFactory实例化对象,所有的ioc容器都是BeanFactory实现类
反射创建对象的方式(进行对象的初始化才能获得一个可用对象,通过context.getBean()获取到对象,因为BeanFactory一开始就是实例化了一个空对象,没有任何属性的):

# 三种方式
# Class<?> aClass = Class.forName("com.node.dubbo.web.SomeController");
# 类.class
# 对象.getClass
aClass.getDeclaredConstructor().newInstance()
# 给对象赋值
xml赋值
<bean id="user" class="com.lj.www.pojo.User"/>
<bean id="person" class="com.lj.www.pojo.Person"/>

<!-- 有参构造方法创建对象 -->
<bean id="user1" class="com.lj.www.pojo.User">
    <constructor-arg index="0" name="id" type="int" value="111"></constructor-arg>
    <constructor-arg index="1" name="name" type="java.lang.String" value="张三"></constructor-arg>
</bean>

<!-- 构造方法的值有对象 -->
<bean id="user2" class="com.lj.www.pojo.User">
    <constructor-arg index="0" name="id" type="int" value="222"></constructor-arg>
    <constructor-arg index="1" name="name" type="java.lang.String" value="李四"></constructor-arg>
    <constructor-arg index="2" name="person" ref="person"></constructor-arg>
</bean>

使用property的方式注入属性值和构造器的方式加载值不一样,会出现循环依赖的问题,前者可以通过set方式解决,后者则不行

<!-- 使用工厂非静态方法创建对象 -->
<bean id="factory" class="com.lj.www.pojo.Factory"/>
<bean id="user3" class="com.lj.www.pojo.User" factory-bean="factory" factory-method="getBean"></bean>

<!-- 装载集合,构造方法上 -->
<bean id="user4" class="com.lj.www.pojo.User">
    <constructor-arg index="0" name="id" type="int" value="333"></constructor-arg>
    <constructor-arg index="1" name="name" type="java.lang.String" value="王五"></constructor-arg>
    <constructor-arg index="2" name="person" ref="person"></constructor-arg>
    <constructor-arg>
        <list>
            <value>足球</value>
            <value>羽毛球</value>
        </list>
    </constructor-arg>
</bean>
<!-- 构造方法有set -->
<bean id="person1" class="com.lj.www.pojo.Person">
    <constructor-arg>
        <set>
            <value></value>
        </set>
    </constructor-arg>
</bean>

3、postProcessor这个类可以拿到原数据信息(这个也是基于BeanDefinition这个bean的定义信息进行构建的),它是可以进行功能的扩展,增强的,而BeanDefinition是给BeanFactory工作的,也就是在BeanFactory实例化对象出来之前,我们可以进行相应的设置,继承了postProcessor的实现类,可以进行比如对对象的属性值进行修改
在ioc容器中,bean对象实例化(空对象),初始化,形成一个完整对象,这一系列过程之间,我们可以是用beanPostProcessor进行相应功能的增强的,分别为前置和后置的BeanPostProcessor在**初始化(赋值的过程)**的前后,那么空对象创建出来之后,实际上下一步就是赋值,我们如果想要修改对象的属性话,需要进行aop技术(实现aop技术有jdk自带的方式和cglib)

Spring AOP includes the following types of advice:

Before:在目标方法被调用之前做增强处理,@Before只需要指定切入点表达式即可
After Returning:在目标方法正常完成后做增强,@AfterReturning除了指定切入点表达式后,还可以指定一个返回值形参名returning,代表目标方法的返回值
After Throwing:主要用来处理程序中未处理的异常,@AfterThrowing除了指定切入点表达式后,还可以指定一个throwing的返回值形参名,可以通过该形参名来访问目标方法中所抛出的异常对象
After:在目标方法完成之后做增强,无论目标方法是否成功完成。@After可以指定一个切入点表达式
Around:环绕通知,在目标方法完成前后做增强处理,环绕通知是最重要的通知类型,像事务,日志等都是环绕通知,注意编程中核心是一个ProceedingJoinPoint,调用ProceedingJoinPoint的proceed()方法才会执行目标方法。

Spring两种代理方式

若目标对象实现了接口,spring默认使用JDK的动态代理。

优点:因为有接口,所以使系统更加松耦合;

缺点:为每一个目标类创建接口;

若目标对象没有实现任何接口,spring使用CGLib进行动态代理。

优点:因为代理类与被代理类是继承关系,所以不需要有接口的存在。

缺点:因为没有使用接口,所以系统的耦合性没有使用JDK的动态代理好。

4、BeanFactory和FactoryBean的区别
FactoryBean有三个方法getObject(), IsSingleton(),getObjectType(),不需要走BeanFactory的一套具有生命周期的对象创建流程,创建一些特殊的bean就采用FactoryBean
5、spring容器起来之后会加载environment的变量信息,getEnv和getProperties

7、正式进入源码
先看refresh核心方法,调用了13个方法
在这里插入图片描述
prepareRefresh就是设置启动时间,创建于存放上下文信息对象的集合
在这里插入图片描述
refreshBeanFactory是called by obtainFreshBeanFactory的方法,创建beanFactory,loadBeanDefinitions(beanFactory)加载bean对象的定义信息,在xml文件中把bean id读取进来
在这里插入图片描述
比如我当前的容器中有22个bean对象在这里插入图片描述
prepareBeanFactory(beanFactory)是给bean工厂进行准备工作,给bean对象设置属性值,进行初始化,上面几步是给整个流程做准备
在这里插入图片描述
看到眼熟的PostProfessor,进行功能增强,BeanFactory调用的
在这里插入图片描述

// Initialize event multicaster for this context.
// 初始化多播器,观察者模式,不同的事件
initApplicationEventMulticaster();

// Initialize other special beans in specific context subclasses.
onRefresh();

// Check for listener beans and register them.
// 注册监听器,不同的事件不同的监听器处理
registerListeners();

finishBeanFactoryInitialization(beanFactory)进行bean对象的实例化,但是只是一个空对象,流程是beanFactory.preInstantiateSingletons() => getBean() => createBean() => doCreateBean() => createBeanInstance() => instantiateBean() => getInstantiationStrategy().instantiate(mbd, beanName, this) => BeanUtils.instantiateClass =>
在这里插入图片描述
这样就创建出空对象,然后进行初始化,第一步是填充属性,调用populateBean(),接着第二步是进行aware方法实现接口需要实现的方法,beanPostProfessor:before的方法,mothod初始化,beanPostProfessor:after的方法在initializeBean方法里面

try {
    this.populateBean(beanName, mbd, instanceWrapper);
    if (exposedObject != null) {
        exposedObject = this.initializeBean(beanName, exposedObject, mbd);
    }
} catch (Throwable var18) {
    if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
        throw (BeanCreationException)var18;
    }

最后finishRefresh,进行清理工作,ioc容器创建完毕

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值