本文纯代码,无享受。
事情发生是这样的:
sb同事:大佬,你知道Spring的bean是怎么放进三级缓存的
我:你问八股文的话,你百度一堆,你问源码的话我没看过spring的源码
sb同事:那你讲讲你的做法,如果让你做三级缓存你会怎么做
我:(把前几天看过dubbo源码的SPI理解揉碎组装成三级缓存)
sb同事:BeanDefinition xxxxx
我(有点烦):你想聊八股文我真没背过
sb同事:spring是不能解决循环依赖的xxxxxxx
。。。。。。。我怕他把我们的应届生都带坏了
我:大佬麻烦你了解以下三级缓存和@Lazy
sb同事:不可能,spring官方文档说了。。。你刚刚说什么L什么?
我:@Lazy
然后sb同事自己折腾了几天之后,拿着一段sb代码打我脸,说lazy也解决不了。我定睛一看,好家伙:
@Bean
@Lazy
public ClassA(ClassB b) {
return new ClassA(b);
}
@Bean
@Lazy
public ClassB(ClassA a) {
return new ClassB(a);
}
算了算了,不跟他多bb自己写东西自己玩把
首先是debug的代码
// CLassA
@Component
public class ClassA {
private ClassB b;
public ClassA(ClassB b) {
this.b = b;
System.out.println("a");
}
}
// CLassB
@Component
public class ClassB {
private ClassA a;
// 不加lazy会启动报错
public ClassB(@Lazy ClassA a){
this.a = a;
System.out.println("B");
}
}
// Controller
@RestController
public class TestController{
@Autowired
private ClassA a;
@Autowired
private ClassB b;
@RequestMapping("testCircle")
public void testaaaa(){
System.out.println(); // 这里打断点
}
}
然后是我自己模拟的Spring加载流程
// ClassA
public class ClassA {
private ClassB b;
public ClassA(@Lazy ClassB b) {
this.b = b;
}
public void write() {
System.out.println("a-a");
}
public void writeB() {
b.write();
}
}
// AopClassA -- 模拟spring没办法生成类的时候生成的代理类
public class AopClassA extends ClassA {
public AopClassA() {
super(null);
}
@Override
public void write() {
System.out.println("AopClassA - write");
ClassA a = (ClassA) TestCircle.getBean(TestCircle.getLowCaresSimpleName(ClassA.class), false);
a.write();
}
@Override
public void writeB() {
System.out.println("AopClassA - writeB");
ClassA a = (ClassA) TestCircle.getBean(TestCircle.getLowCaresSimpleName(ClassA.class), false);
a.writeB();
}
}
// ClassB
public class ClassB {
private ClassA a;
public ClassB(ClassA a) {
this.a = a;
}
public void writeA() {
a.write();
}
public void write() {
System.out.println("b-b");
}
}
// AopClassB -- 模拟spring没办法生成类的时候生成的代理类
public class AopClassB extends ClassB {
public AopClassB() {
super(null);
}
@Override
public void writeA() {
System.out.println("AopClassB - writeA");
ClassB b = (ClassB) TestCircle.getBean(TestCircle.getLowCaresSimpleName(ClassB.class), false);
b.writeA();
}
@Override
public void write() {
System.out.println("AopClassB - write");
ClassB b = (ClassB) TestCircle.getBean(TestCircle.getLowCaresSimpleName(ClassB.class), false);
b.write();
}
}
测试类及相关工具类
public class TestCircle {
private static Map<String, Object> cache1 = new ConcurrentHashMap<>();
private static Map<String, Object> cache2 = new ConcurrentHashMap<>();
private static Map<String, Object> cache3 = new ConcurrentHashMap<>();
@SneakyThrows
public static void main(String[] args) {
// 假装Component只扫描到这两个类
Class<?>[] clazzArr = new Class[2];
clazzArr[0] = ClassA.class;
clazzArr[1] = ClassB.class;
for (Class<?> aClass : clazzArr) {
// 模拟实例化
Constructor<?>[] constructors = aClass.getConstructors();
// 忽略构造函数的筛选规则
Constructor<?> constructor = constructors[0];
Annotation[][] parameterAnnotations = constructor.getParameterAnnotations();
Class<?>[] parameterTypes = constructor.getParameterTypes();
Object[] objects = new Object[parameterTypes.length];
for (int i = 0; i < parameterTypes.length; i++) {
objects[i] = getBean(getLowCaresSimpleName(parameterTypes[i]), isLazy(parameterAnnotations[i]));
}
cache1.put(getLowCaresSimpleName(aClass), constructor.newInstance(objects));
}
System.out.println("----- classA -----");
ClassA a = (ClassA) cache1.get(getLowCaresSimpleName(ClassA.class));
a.write();
a.writeB();
System.out.println("----- classB -----");
ClassB b = (ClassB) cache1.get(getLowCaresSimpleName(ClassB.class));
b.write();
b.writeA();
System.out.println();
}
public static String getLowCaresSimpleName(Class<?> clazz) {
char[] chars = clazz.getSimpleName().toCharArray();
chars[0] = Character.toLowerCase(chars[0]);
return new String(chars);
}
public static boolean isLazy(Annotation[] parameterAnnotations) {
for (Annotation parameterAnnotation : parameterAnnotations) {
if (parameterAnnotation.annotationType().equals(Lazy.class)) {
return true;
}
}
return false;
}
public static Object getBean(String name, boolean isLazy) {
Object o = cache1.get(name);
if (Objects.nonNull(o)) return o;
o = cache2.get(name);
if (Objects.nonNull(o)) /* 省略初始化 */ return o;
o = cache3.get(name);
if (Objects.nonNull(o)) /* 省略实例化和初始化*/ return o;
if (isLazy) {
// 模拟从三级缓存获取代理a和b
if ("classA".equals(name)) {
AopClassA aopClassA = new AopClassA();
cache3.put("classA", aopClassA);
return aopClassA;
}
if ("classB".equals(name)) {
AopClassB aopClassB = new AopClassB();
cache3.put("classB", aopClassB);
return aopClassB;
}
}
return null;
}
}
总结:我也不知道我对不对,但是从debug的角度来讲差不多是这样,当然一切问题还是要在我读完dubbo之后读spring才能解决。
但最起码我这是一个很好的思路,不是么。