先以xml方式,首先添加俩个类 A,B
public class A {
private B b;
public B getB() {
return b;
}
public void setB(B b) {
this.b = b;
}
}
public class B {
}
下面上配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<bean name="a" class="com.gee.demo.entity.A" depends-on="b" ></bean>
<bean name="b" class="com.gee.demo.entity.B"></bean>
</beans>
测试方法
public class Config {
public static void main(String args[]) {
ApplicationContext applicationContext = new FileSystemXmlApplicationContext("classpath:application-config.xml");
System.out.println(applicationContext.getBean(A.class));
System.out.println(applicationContext.getBean(B.class));
}
}
最后输出
com.gee.demo.entity.A@45afc369
com.gee.demo.entity.B@799d4f69
说明注入是成功的
那么试一下注解方式
调整A,B的代码
@Component
@DependsOn(value = "b")
public class A {
}
@Component
public class B {
}
测试方法
@Configuration
@ComponentScan(basePackages = "com.gee")
public class Config {
public static void main(String args[]) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Config.class);
System.out.println(applicationContext.getBean(A.class));
System.out.println(applicationContext.getBean(B.class));
}
}
最后输出
com.gee.demo.entity.A@2aa3cd93
com.gee.demo.entity.B@7ea37dbf
说明是成功的
那么下面问题来了,互相依赖会怎么办
此时我们调整代码
@Component
@DependsOn(value = "b")
public class A {
}
@Component
@DependsOn(value = "a")
public class B {
}
再次执行同样的测试方法,抛出异常。
警告: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'b' defined in file [/Users/huangzhaoji/eclipse-workspace/springframework-demo/target/classes/com/gee/demo/entity/B.class]: Circular depends-on relationship between 'b' and 'a'
调整xml,改为A,B相互依赖
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<bean name="a" class="com.gee.demo.entity.A" depends-on="b" ></bean>
<bean name="b" class="com.gee.demo.entity.B" depends-on="a"></bean>
</beans>
运行xml的测试方法
public class Config {
public static void main(String args[]) {
ApplicationContext applicationContext = new FileSystemXmlApplicationContext("classpath:application-config.xml");
System.out.println(applicationContext.getBean(A.class));
System.out.println(applicationContext.getBean(B.class));
}
}
此时就报错了。
在DefaultSingletonBeanRegistry有一个方法是用于判断,是否出现循环依赖的。
private boolean isDependent(String beanName, String dependentBeanName, @Nullable Set<String> alreadySeen) {
if (alreadySeen != null && alreadySeen.contains(beanName)) {
return false;
}
String canonicalName = canonicalName(beanName);
//其实这个map就记录了依赖于这个类的所有类
Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
if (dependentBeans == null) {
return false;
}
//若依赖b的类,包含a,而此时b依赖a,则说明是循环依赖,返回true,随后就会抛出异常了。
if (dependentBeans.contains(dependentBeanName)) {
return true;
}
for (String transitiveDependency : dependentBeans) {
if (alreadySeen == null) {
alreadySeen = new HashSet<>();
}
alreadySeen.add(beanName);
if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) {
return true;
}
}
return false;
}
网友评论