什么是循环依赖?
所谓循环依赖就是A依赖B的同时B又依赖A,二者互相依赖,形成环路。试想,SpringIOC在初始化容器的时候,先实例化BeanA,发现BeanA依赖于BeanB,于是先去实例化BeanB,发现BeanB又依赖于BeanA,这就造成了循环依赖,如果程序不处理这种情况,就会陷入死循环,无限执行下去,直到程序崩溃。
我们今天要解决的问题就是摸清spring在初始化容器的时候是怎么解决循环依赖这个问题的。这里将以annotation注解注入的方式分析SpringIOC初始化过程。
引入依赖:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.11.RELEASE</version>
</dependency>
新建测试类:
@Component
public class AnnotationLeader {
@Autowired
private LeaderDepender leaderDepender;
public AnnotationLeader() {
System.out.println("Leader started........");
}
public void output() {
System.out.println("my id is :" + leaderDepender.getId());
}
}
@Component
public class LeaderDepender {
private String id ;
@Autowired
private AnnotationLeader annotationLeader;
public LeaderDepender() {
this.id = "123456";
System.out.println("Depender started........");
}
public String getId() {
return id;
}
}
public class AnnotationAppStartTest {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext("com.cf.spring.code");
AnnotationLeader leader = context.getBean(AnnotationLeader.class);
leader.output();
}
}
进入容器启动构造方法:new AnnotationConfigApplicationContext("com.cf.spring.code");
public AnnotationConfigApplicationContext(String... basePackages) {
// 注册bean扫描器和bean读取器
this();
// 这一步很关键,扫描包路径下所有的class文件,解析成BeanDefinition并注册BeanDefinition
scan(basePackages);
refresh();
}
public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
与此同时,子类执行构造方法之前会执行父类GenericApplicationContext的构造方法
public GenericApplicationContext() {
// 初始化bean工厂
this.beanFactory = new DefaultListableBeanFactory();
}
回过头来看scan(basePackages):
public void scan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
this.scanner.scan(basePackages);
}
public int scan(String... basePackages) {
// 获取已注册bean的数量
int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
// 重点,往下看
doScan(basePackages);
// Register annotation config processors, if necessary.
if (this.includeAnnotationConfig) {
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
}
doScan在ClassPathBeanDefinitionScanner中
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
// 定义容器存储要返回的beanDefinition包装类
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>();
// 可能有多个包扫描路径,遍历要扫描的路径
for (String basePackage : basePackages) {
// 在这里得到了BeanDefinition,足以说明此方法的重要性,下面方法先忽略,先跟进去看看
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition) {
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
public Set<BeanDefinition> findCandidateComponents(String basePackage) {
Set<BeanDefinition> candidates = new LinkedHashSet<BeanDefinition>();
try {
// 组装包扫描路径,将包名转换成路径(最终格式:classpath*:com/cf/spring/code/**/*.class)
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage(basePackage) + '/' + this.resourcePattern;
// 根据扫描路径得到资源对象数组
Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath);
boolean traceEnabled = logger.isTraceEnabled();
boolean debugEnabled = logger.isDebugEnabled();
// 遍历资源对象数组,根据每个资源对象获取beanDefinition
for (Resource resource : resources) {
if (traceEnabled) {
logger.trace("Scanning " + resource);
}
if (resource.isReadable()) {
try {
// MetadataReader这个类里面包含了类的元数据和注解的元数据信息
MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);
// 是否为候选组件,判断是否满足bean注入条件,如果有@Conditional注解,则跳过。判断是否有@Component、@Repository、@Service、@Controller标注
if (isCandidateComponent(metadataReader)) {
// 根据matadateReader构造BeanDefinition
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
sbd.setResource(resource);
sbd.setSource(resource);
if (isCandidateComponent(sbd)) {
if (debugEnabled) {
logger.debug("Identified candidate component class: " + resource);
}
// 添加到BeanDefinition集合中,用于返回数据
candidates.add(sbd);
}
else {
if (debugEnabled) {
logger.debug("Ignored because not a concrete top-level class: " + resource);
}
}
}
else {
if (traceEnabled) {
logger.trace("Ignored because not matching any filter: " + resource);
}
}
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to read candidate component class: " + resource, ex);
}
}
else {
if (traceEnabled) {
logger.trace("Ignored because not readable: " + resource);
}
}
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
}
return candidates;
}