Spring IOC循环依赖

什么是循环依赖?

所谓循环依赖就是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;
	}
发布了5 篇原创文章 · 获赞 7 · 访问量 1469

猜你喜欢

转载自blog.csdn.net/Epoch_Elysian/article/details/105302736