Spring循环依赖实例
spring单例默认是支持循环依赖的
首先看一下循环依赖是什么,代码如下:
Bean工厂中的两个类: @Component public class IndexService { @Autowired UserService userService; public IndexService () { System.out.println("IndexService"); } public void getService() { System.out.println(userService); } } @Component public class UserService { public UserService() { System.out.println("Userservice"); } }
IndexService中注入了userService.
写一个测试类:
public class test { public static void main(String[] args) { AnnotationConfigApplicationContext configApplicationContext = new AnnotationConfigApplicationContext(SpringConfig.class); // configApplicationContext.getBean(IndexService.class).getService(); IndexService indexService = configApplicationContext.getBean(IndexService.class); // UserService userService = configApplicationContext.getBean(UserService.class); System.out.println(indexService); } }
控制台返回:
IndexService
Userservice
com.springtest.springclass.IndexService@3fd7a715
接下来讲一下循环依赖整个过程:
1、扫描scan包含注解的类;
2、解析parse这些类:
new Map();//底层会有一个map来存放每一个类的BeanDefinition,key是类名,value就是beanDefinition
new List(String);
//循环解析
for() {
//1、先new一个BeanDefinition对象
GenericBeanDefinition genericBeanDefinition = new GenericBeanDefinition();
//2、将类信息放进genericBeanDefinition中
genericBeanDefinition.setBeanClass(UserService.class);
genericBeanDefinition.setBeanClassName(“UserService”);
。
。//此处省略其他的类信息
//3、将这个genericBeanDefinition put进一个map中(key是类的名字)
map.put(“UserService”, genericBeanDefinition );
//4、List(String)存放的是这些类的名字
List(String).add(“UserService”);
}
3、调用扩展(BeanFactryPostProcessor):
遍历上面的map,做一些校验(如:需不需要new一个(你这bean是单例,还是原型,如果是原型的不会去new,当在调用getBean方法时才会去new)、构造方法有没有参数等)
4、创建(new)一个对象
部分源码,自己写一个类实现BeanFactoryPostProcessor接口,用来对BeanDefinition的处理;
@Component public class ZywBeanDefinitionTest implements BeanFactoryPostProcessor{ @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException { //取出indexUservice的BeanDefinition GenericBeanDefinition indexService = (GenericBeanDefinition) configurableListableBeanFactory.getBeanDefinition("indexService"); //将UserService注入容器 indexService.setBeanClass(UserService.class); } }
可以点进getBeanDefinition的源码:
public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
//可以看到是从一个map中取的 BeanDefinition bd = (BeanDefinition)this.beanDefinitionMap.get(beanName); if(bd == null) { if(this.logger.isTraceEnabled()) { this.logger.trace("No bean named '" + beanName + "' found in " + this); } throw new NoSuchBeanDefinitionException(beanName); } else { return bd; } }
测试,将UserService上的@Component注解注释掉(目的是不会解析生成UserService的BeanDefinition,此处是通过IndexService的BeanDefinition来创建Uservice)
@Component
public class IndexService {
// @Autowired
// UserService userService;
public IndexService () {
System.out.println("IndexService");
}
// public void getService() {
// System.out.println(userService);
// }
}
//@Component public class UserService { public UserService() { System.out.println("Userservice"); } }
public class test { public static void main(String[] args) { AnnotationConfigApplicationContext configApplicationContext = new AnnotationConfigApplicationContext(SpringConfig.class); // configApplicationContext.getBean(IndexService.class).getService(); // IndexService indexService = configApplicationContext.getBean(IndexService.class); UserService userService = configApplicationContext.getBean(UserService.class);//此处获取的是UserService对象,如果获取的是IndexService对象会报错!!!!! System.out.println(userService); } }
输出结果:
Userservice
com.springtest.springclass.UserService@7c29daf3

浙公网安备 33010602011771号