『spring』Java面试题:Spring如何解决的循环依赖( 二 )
当然了 , 这个地步你肯定要结合Spring源码来看 , 要不肯定看不懂 。
【『spring』Java面试题:Spring如何解决的循环依赖】如果你只是想大概了解 , 或者面试 , 可以先记住笔者上文提到的“三级缓存” , 以及下文即将要说的本质 。
循环依赖的本质
上文了解完Spring如何处理循环依赖之后 , 让我们跳出“阅读源码”的思维 , 假设让你实现一个有以下特点的功能 , 你会怎么做?阅读源码的几个小技巧 , 这篇推荐看下 。
- 将指定的一些类实例为单例
- 类中的字段也都实例为单例
- 支持循环依赖
public class A {
private B b;
类B:
public class B {
private A a;
说白了让你模仿Spring:假装A和B是被@Component修饰 ,
并且类中的字段假装是@Autowired修饰的 , 处理完放到Map中 。
其实非常简单 , 笔者写了一份粗糙的代码 , 可供参考:
/**
* 放置创建好的bean Map
*/
private static Map<String Object> cacheMap = new HashMap<>(2);
public static void main(String[
args) {
// 假装扫描出来的对象
Class[
classes = {A.class B.class;
// 假装项目初始化实例化所有bean
for (Class aClass : classes) {
getBean(aClass);
// check
System.out.println(getBean(B.class).getA() == getBean(A.class));
System.out.println(getBean(A.class).getB() == getBean(B.class));
@SneakyThrows
private static <T> T getBean(Class<T> beanClass) {
// 本文用类名小写 简单代替bean的命名规则
String beanName = beanClass.getSimpleName().toLowerCase();
// 如果已经是一个bean , 则直接返回
if (cacheMap.containsKey(beanName)) {
return (T) cacheMap.get(beanName);
// 将对象本身实例化
Object object = beanClass.getDeclaredConstructor().newInstance();
// 放入缓存
cacheMap.put(beanName object);
// 把所有字段当成需要注入的bean , 创建并注入到当前bean中
Field[
fields = object.getClass().getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
// 获取需要注入字段的class
Class<?> fieldClass = field.getType();
String fieldBeanName = fieldClass.getSimpleName().toLowerCase();
// 如果需要注入的bean , 已经在缓存Map中 , 那么把缓存Map中的值注入到该field即可
推荐阅读
- 『Java』java数据结构系列——什么是数据结构
- 『Java』马云:成功人跟普通人差不多,但这三点我一定要分享给所有年轻人
- #Java#java线程到底有多少种状态?
- #智能手表#1、初识java-1
- [华为]有朋友问我“JAVA全栈”、“互联网架构师”和“JAVAEE”到底是什么?
- 「javascript」这边走Javascript了解一下
- 「华为」一篇有趣的Java class
- struts@Java面试之项目面试问题——不看面试会后悔的
- 「Java」六面蚂蚁金服,唬住了面试官要了30K;其实Java面试也没那么难
- Java@23种java设计模式之:建造者模式、工厂方法模式、抽象工厂模式!