一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情。
一、Spring容器启动流程
创建配置类
@ComponentScan(value = {"com.woniu"})
@Configuration
public class MyConfig {
}
创建一个普通类
package com.woniu.service;
import org.springframework.stereotype.Component;
@Component
public class Eservice {
}
创建一个启动类
public class Application {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
}
}
在启动类的第三行打断点开始单步调试,进入spring的容器启动流程
这个方法非常重要,在循环依赖中对于同一个bean会多次调用,先从一级缓存中查询是否存在bean,若不存在,再从二级缓存中查询是否存在bean,如果还是没有找到,从三级缓存中查询singletonFactory,如果没有,则直接返回,若在三级缓存中找到singletonFactory,则调用工厂中的方法创建bean,然后在把bean添加到二级缓存中
什么是三级缓存
二、简单依赖注入
再创建一个普通类
package com.woniu.service;
import org.springframework.stereotype.Component;
@Component
public class Fservice {
}
修改一下Eservice,注入Fservice实例
package com.woniu.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Eservice {
@Autowired
private Fservice fservice;
}
在这个populateBean里面注入Fservice的实例到Eservice中
上面截图中的descriptor.resolveCandidate方法继续跟踪会进入到下面截图的方法,注意,这时候,需要从容器中查找Fservice的实例对象了
下面就正式进入创建一个Fservice对象的实例,并且添加到spring的容器中,也就是第一部分讲的spring容器启动流程
把创建好的fservice实例返回给刚才正在处理@Autowired的注解的代码
程序继续运行,把eservice也加入到一级缓存
三、AOP依赖注入
修改MyConfig
package com.woniu;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@ComponentScan(value = {"com.woniu"})
@EnableAspectJAutoProxy
@Configuration
public class MyConfig {
}
创建MyAop类
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class MyAop {
//用来定义切入点表达式的方法,方法名就是切入点表达式的名称
@Pointcut("execution(* com.woniu.service..*.*(..))")
public void pt1(){ }
@Before("pt1()")
public void Before() throws Throwable {
System.out.println("before aop...");
}
}
Eservice
package com.woniu.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Eservice {
@Autowired
private Fservice fservice;
}
Fservice
package com.woniu.service;
import org.springframework.stereotype.Component;
@Component
public class Fservice {
public void print(){
System.out.println("fservice");
}
}
启动类
package com.woniu;
import com.woniu.service.*;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
public class Application {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
}
}
此时fservice的原生bean已经实例已经创建完成,initializeBean这个方法将会做初始化,在这里,将会给fservice生成一个代理对象
这个BeanPostProcessor会为Fservice生成代理对象,并且放置在二级缓存
earlyProxyReferences可以帮助判断是否已经生成过代理对象,wrapIfNecessary这个方法就是生成代理对象的方法
创建代理工厂
fservice的代理对象已经被创建出来
initializeBean方法调用完毕,Fservicve代理对象创建完毕
此时的一级缓存如下
至此Eservice对象的initializeBean方法执行完毕,fservice的代理对象已经被注入到eservice中
四、循环依赖
-
非单例V.S非单例
-
单例构造函数V.S单例构造函数
-
单例构造函数V.S单例普通依赖注入
-
单例普通依赖注入V.S单例普通依赖注入
-
AOP单例普通依赖注入V.SAOP单例普通依赖注入****