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容器创建完毕