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 );

      //4List(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

 


posted @ 2020-08-09 20:49  杯莫停、  阅读(569)  评论(0)    收藏  举报