手写BeanFactory(三级缓存)

268 阅读11分钟

概述

看了好久spring源码,有些地方理解的不深刻,决定手写一下BeanFactory来加深理解

规范

spring中最主要的bean工厂实现就是DefaultListableBeanFactory,看一下它实现的接口

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
		implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable

主要实现两个接口ConfigurableListableBeanFactoryBeanDefinitionRegistry,下面分别整理下这两个接口要实现的方法

BeanDefinitionRegistry

这个简单,从字面理解就是一个bean定义的注册器,那自然可以填加,也可以获取bean定义 重点方法:

  • void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) 这就是注册bean定义
  • BeanDefinition getBeanDefinition(String beanName) 获取bean定义

总结就是,作为一个bean定义注册器,需要实现可以注册,完事也可以获取,一句话概括就是一个bean定义存储的容器

ConfigurableListableBeanFactory

这个相对复杂,字面理解是一个可配置可列出的bean工厂 重点方法(包含了父接口):

  • Object getBean(String name) 获取bean,最主要的方法,bean工厂吗,当然主要的任务就是能获取bean(当然没有则创建)
  • void preInstantiateSingletons() 预初始化所有单例bean(当然是根据注册的bean定义来初始化)

SingletonBeanRegistry

这个倒不是bean工厂的接口,而是DefaultListableBeanFactory的子类DefaultSingletonBeanRegistry实现的接口

image.png

看名字就知道这是一个存储单例bean的容器,著名的三级缓存就在这里

  • void registerSingleton(String beanName, Object singletonObject) 注册单例对象
  • Object getSingleton(String beanName) 获取单例对象

也就是他是一个对象存储的容器,就像一个hashmap

总结

也就是说DefaultListableBeanFactory是一个bean工厂,可以获取bean,可以提前初始化所有bean,同时它也是一个bean定义的容器。 而他的bean实际存储就是交给他的子类DefaultSingletonBeanRegistry处理的

image.png

实现

之所以研究DefaultSingletonBeanRegistry的骨架,是为了模仿,因为手写模仿最好得跟它保持相同的规范和设计思路,要不回头看源码还是看不懂 所以我的实现思路也是首先要实现两个接口,然后按照他的bean存储方式,也写个singletonBeanRegistry用来继承

注:以下所有代码由于继承了spring的接口,所有要有很多实现方法,只贴了重点实现的方法,其它方法全默认

一.简单的bean工厂

先考虑最简单的实现方式,两个容器两个hashMap完全可以实现,那就试一下 原来的spring的bean定义有点复杂,不在本届的讨论范围,所以自己实现了个简单的bean定义(只存储类的信息)

public class MyBeanDefinition implements BeanDefinition {
	// 存储class
	private Class<?> beanClass;
	
	// 简单的bean定义,只存储class信息
	public MyBeanDefinition(Class<?> beanClass) {
		this.beanClass = beanClass;
	}

	public Class<?> getBeanClass() {
		return beanClass;
	}

一个简单的bean定义实现了,下面实现bean工厂,首先实现一个bean的容器

public class MySingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {

	/** bean容器,一级缓存 **/
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

	/** 添加bean **/
	@Override
	public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
		this.singletonObjects.put(beanName, singletonObject);
	}

	/** 获取bean **/
	@Override
	public Object getSingleton(String beanName) {
		return this.singletonObjects.get(beanName);
	}

其实就是一个HashMap包装成一个类

实现BeanFactory

public class MyBeanFactory extends MySingletonBeanRegistry implements ConfigurableListableBeanFactory, BeanDefinitionRegistry {

	/** bean定义容器 **/
	private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

	/**
	 * 注册bean定义
	 */
	@Override
	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
		beanDefinitionMap.put(beanName, beanDefinition);
	}

	/**
	 * 获取bean定义
	 */
	@Override
	public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
		return this.beanDefinitionMap.get(beanName);
	}

	/**
	 * 提前初始化所有bean
	 * @throws BeansException
	 */
	@Override
	public void preInstantiateSingletons() throws BeansException {
		// 循环所有bean定义
		for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
			// 生产bean
			getBean(entry.getKey());
		}
	}

	/**
	 * 获取bean
	 */
	@Override
	public Object getBean(String name) throws BeansException {
		try {
			// 先去容器里拿
			Object singleton = getSingleton(name);
			// 如果没有就创建
			if (singleton==null) {
				// 获取bean定义
				MyBeanDefinition beanDefinition = (MyBeanDefinition) getBeanDefinition(name);
				// 实例化bean
				singleton = beanDefinition.getBeanClass().newInstance();
				// 注册到容器
				registerSingleton(name, singleton);
			}
			return singleton;
		} catch (InstantiationException e) {
			return null;
		} catch (IllegalAccessException e) {
			return null;
		}
	}

就这么简单实现了,bean定义容器也是一个map,getBean就拿到class放射成实例就行了,测试一下 新建两个测试对象

public class BeanA {     
   public String aName = "A";
}
public class BeanB {     
   public String bName = "B";
}

测试:

System.out.println("===factory1===");
MyBeanFactory1 myBeanFactory1 = new MyBeanFactory1();
myBeanFactory1.registerBeanDefinition("BeanA", new MyBeanDefinition(BeanA.class));
myBeanFactory1.preInstantiateSingletons();
Object a1 = myBeanFactory1.getBean("BeanA");
System.out.println(a1);

输出

===factory===
{"A":{"aName":"A"}}

完全没问题

依赖注入

很显然,一中的实现最简单,但如果需要依赖注入,它就做不到了,那么如何实现依赖注入? spring依赖注入需要一个注解@Autowired,我们也写一个注解MyAutowired

@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAutowired {
}

这时,两个对象修改这样

public class BeanA {
	public String aName = "A";
         // 想通过依赖注入进beanB
	@MyAutowired
	public BeanB beanB;

	@Override
	@AopToString
	public String toString() {
		return "{\"A\":{"
				+ "\"aName\":\""
				+ aName + '\"'
				+ ",\"b\":"
				+ (null==beanB?"null":beanB.bName)
				+ "}}";

	}
}
public class BeanB {
	
	public String bName = "B";

	@Override
    @AopToString
	public String toString() {
		return "{\"B\":{"
				+ "\"bName\":\""
				+ bName + "}}";

	}
}

实现起来也不难,思路如下: 实例化对象后,循环所有属性,发现@MyAutowired,调用getBean("属性名")获取另一个bean,再给属性赋值,只需修改getBean方法即可

/**
 * 获取bean
 */
@Override
public Object getBean(String name) throws BeansException {
    try {
        // 先去容器里拿
        Object singleton = getSingleton(name);
        // 如果没有就创建
        if (singleton==null) {
            // 获取bean定义
            MyBeanDefinition beanDefinition = (MyBeanDefinition) getBeanDefinition(name);
            // 实例化bean
            singleton = beanDefinition.getBeanClass().newInstance();
            // 填充属性(新增)
            popular(singleton, beanDefinition.getBeanClass());
            // 注册到容器
            registerSingleton(name, singleton);
        }
        return singleton;
    } catch (InstantiationException e) {
        return null;
    } catch (IllegalAccessException e) {
        return null;
    }
}

实例化完,新增了个填充属性popular方法 实现如下

private void popular(Object singleton, Class<?> clazz) {
    // 循环属性
    for (Field declaredField : clazz.getDeclaredFields()) {
        // 看看是否有MyAutowired注解
        MyAutowired annotation = declaredField.getAnnotation(MyAutowired.class);
        if (annotation!=null) {
            declaredField.setAccessible(true);
            try {
                // 属性赋值
                declaredField.set(singleton, getBean(declaredField.getType().getSimpleName()));
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }
}

流程是这样的 1.实例化A 2.循环A属性 3.发现需要B 4.实例化B 5.将实例化的B赋值给A对象的属性 总之就是A要等B创建完,A才能创建完 测试一下原测试方法,输出

===factory===
{"A":{"aName":"A","b":B}}

可以看到实现了,依赖注入

循环依赖

上文解决了依赖注入,但没有办法解决循环依赖,比如

public class BeanA {
	public String aName = "A";
         // 想通过依赖注入进beanB
	@MyAutowired
	public BeanB beanB;

	@Override
	@AopToString
	public String toString() {
		return "{\"A\":{"
				+ "\"aName\":\""
				+ aName + '\"'
				+ ",\"b\":"
				+ (null==beanB?"null":beanB.bName)
				+ "}}";

	}
}
public class BeanB {
	
	public String bName = "B";

	@MyAutowired
	public BeanA beanA;

	@Override
	public String toString() {
		return "{\"BeanB\":{"
				+ "\"bName\":\""
				+ bName + '\"'
				+ ",\"beanA\":"
				+ (null==beanA?"null":beanA.aName)
				+ "}}";

	}
}

这时候A不光需要B,B也需要A,如果还按照上面的方法那么A要等B创建完,B又要等A创建完,那就永远不会创建出来了,死循环,最终StackOverflowError

  • 解决思路1 方案:preInstantiateSingletons方法先实例化所有bean并存入一级缓存,然后所有bean再循环填充属性,而getBean只是从bean容器获取,没有创建功能 问题:这样做完全可以解决循环依赖,我当时想到的解法就是这样,但是spring没这么做,原因其实也很简单,这样做只适合同时初始化所有bean,但preInstantiateSingletons方法只是实例化非懒汉模式的单例bean,但因为懒加载的存在,要求getBean方法必须获取完整的bean对象,这种解法就完全行不通
  • 解决思路2 方案:实例化后马上存入一级缓存,然后再去填充属性,这样先A后B的话,先实例化A,存入一级缓存,A填充属性,实例化B,B存入一级缓存,B填充属性,需要A而且一级缓存有,直接获取填充B,回到A的getBean再给A的b属性赋值 问题:这种方案也可以解决循环依赖,但是会出现一个问题,bean在实例化时就已经放入一级缓存,这时候的bean是一个不完整的bean,如果被获取到很容易出问题
  • 解决思路3 方案:在2的基础上做优化,再添加一层缓存,名曰“二级缓存”(存放不完整的bean),实例化的bean先放入二级缓存并标志正在创建,获取单例对象时,如果正在创建则从二级缓存取bean做属性填充,最后完整的bean存入一级缓存 问题:无,这就是spring的解决思路

解决方案已出,下面写代码,首先bean容器MySingletonBeanRegistry需要加入二级缓存,并加入是否正在创建标识功能

public class MySingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {

	/** bean容器,一级缓存 **/
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

	/** bean容器,二级缓存 **/
	private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

	/** 存储正在创建的bean **/
	private final Set<String> singletonsCurrentlyInCreation =
			Collections.newSetFromMap(new ConcurrentHashMap<>(16));

	/**
	 * 查看bean是否正在创建
	 */
	public boolean isSingletonCurrentlyInCreation(String beanName) {
		return this.singletonsCurrentlyInCreation.contains(beanName);
	}

	/**
	 * 标志bean正在创建
	 */
	protected void beforeSingletonCreation(String beanName) {
		this.singletonsCurrentlyInCreation.add(beanName);
	}

	/**
	 * 标志bean创建完成
	 */
	protected void afterSingletonCreation(String beanName) {
		this.singletonsCurrentlyInCreation.remove(beanName);
	}

	/**
	 * 添加bean二级缓存
	 */
	protected void addEarly(String beanName, Object singletonObject) {
		this.earlySingletonObjects.put(beanName, singletonObject);
	}

	/** 添加bean **/
	@Override
	public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
		this.singletonObjects.put(beanName, singletonObject);
	}

	/** 获取bean **/
	@Override
	public Object getSingleton(String beanName) {
		// 一级缓存拿
		Object singletonObject = this.singletonObjects.get(beanName);
		// 如果拿不到并且正在创建,去二级缓存拿
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			singletonObject = this.earlySingletonObjects.get(beanName);
		}
		return singletonObject;
	}

而BeanFactory需要做的修改,就是getBean 标记(改)

/**
 * 获取bean
 */
@Override
public Object getBean(String name) throws BeansException {
    try {
        // 先去容器里拿
        Object singleton = getSingleton(name);
        // 如果没有就创建
        if (singleton==null) {
            // 标记正在创建(改)
            beforeSingletonCreation(name);
            // 获取bean定义
            MyBeanDefinition beanDefinition = (MyBeanDefinition) getBeanDefinition(name);
            // 实例化bean
            singleton = beanDefinition.getBeanClass().newInstance();
            // 提前暴露加到二级缓存(改)
            addEarly(name, singleton);
            // 填充属性
            popular(singleton, beanDefinition.getBeanClass());
            // 注册到容器
            registerSingleton(name, singleton);
            // 标记创建完成(改)
            afterSingletonCreation(name);
        }
        return singleton;
    } catch (InstantiationException e) {
        return null;
    } catch (IllegalAccessException e) {
        return null;
    }
}

测试一下

System.out.println("===factory===");
MyBeanFactory myBeanFactory = new MyBeanFactory();
myBeanFactory.registerBeanDefinition("BeanA", new MyBeanDefinition(BeanA.class));
myBeanFactory.registerBeanDefinition("BeanB", new MyBeanDefinition(BeanB.class));
myBeanFactory.preInstantiateSingletons();
Object a = myBeanFactory.getBean("BeanA");
Object b = myBeanFactory.getBean("BeanB");
System.out.println(a);
System.out.println(b);

输出

{"A":{"aName":"A","b":B}}
{"B":{"bName":"B","a":A}}

彻底解决了循环依赖

网上人都说二级缓存是为了解决循环依赖,实际上二级缓存是为了解决循环依赖造成的bean不完整问题

代理

解决了循环依赖问题,看下一个问题:动态代理 spring除了IOC,最津津乐道的功能就是AOP,所以再spring的设计中肯定需要考虑AOP 那我们模拟下AOP,先加一个注解

@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AopToString {
}

然后修改两个bean, 再toString方法上都加上该注解

@AopToString
public String toString() {

然后beanFactory发现方法有@AopToString注解就是用cglib方法生成一个动态代理(再toSring之前输出"TO String AOP"),最终存入bean容器的是这个动态代理对象而不是通过反射创建出的对象,一个AOP就实现了

但问题出现了,什么时候创建代理? 答:考虑到循环依赖,那么肯定是在添加二级缓存前,因为代理对象和实例化出来的对象是两个对象,假如A存在代理,B的依赖注入是A的原对象,那不是打错特错了吗。所以一定是添加二级缓存前前创建代理,代码实现一下,beanFactory修改

/**
 * 获取bean
 */
@Override
public Object getBean(String name) throws BeansException {
    try {
        // 先去容器里拿
        Object singleton = getSingleton(name);
        // 如果没有就创建
        if (singleton==null) {
            // 标记正在创建
            beforeSingletonCreation(name);
            // 获取bean定义
            MyBeanDefinition beanDefinition = (MyBeanDefinition) getBeanDefinition(name);
            // 实例化bean
            singleton = beanDefinition.getBeanClass().newInstance();
            //创建代理(新增)
            singleton = createBeanProxy(singleton, beanDefinition.getBeanClass());
            // 提前暴露加到二级缓存
            addEarly(name, singleton);
            // 填充属性
            popular(singleton, beanDefinition.getBeanClass());
            // 注册到容器
            registerSingleton(name, singleton);
            // 标记创建完成
            afterSingletonCreation(name);
        }
        return singleton;
    } catch (InstantiationException e) {
        return null;
    } catch (IllegalAccessException e) {
        return null;
    }
}
private Object createBeanProxy(Object singleton, Class<?> clazz) {
    Method[] Methods = clazz.getMethods();
    // 循环所有方法
    for (Method field : Methods) {
        // 如果存在AopToString注解(简化处理只代理一个)
        if (field.isAnnotationPresent(AopToString.class)) {
            // 使用cglib创建代理
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(clazz);
            enhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> {
                if (method.equals(field)) {
                    // 代理对象toSpring前输出
                    System.out.print("TO String AOP ");
                }
                return methodProxy.invokeSuper(o, objects);
            });
            return enhancer.create();
        }
    }
    return singleton;
}

测试一下原测试方法

TO String AOP {"A":{"aName":"A","b":B}}
{"B":{"bName":"B","a":A}}

再循环依赖的前提下实现了动态代理

三级缓存

网上都说三级缓存为了解决动态代理,但其实到现在为止,只有二级缓存,动态代理也解决了 那要三级缓存干嘛呐,没有看见过官方的解释,但是根据读源码猜测又这几个考虑

  • spring的设计思路,动态代理创建应该是最后一步,应该在所有事情(实例化,填充属性,初始化)之后执行
  • spring其实并不太希望出现循环依赖(新版的已经默认禁止循环依赖)
  • 为了不提倡的循环依赖而把动态代理的创建时机提前,不值得

最终的实现方案:一般情况最后一步创建代理,如果出现循环依赖,提前创建代理 这个其实挺难实现的,因为在某个getBean执行时候是没有办法确定是否存在循环依赖的,而且要在填充属性前确定,这更难了。 spring的解决方案: 再加个三级缓存

  • 如果出现循环依赖 getBean(A)时,取消原来创建代理后存储二级缓存的步骤,修改为存创建代理的方法至三级缓存,如果出现循环依赖getBean(B)的时候又反过来调用getBean(A),会去bean容器查找,此时二级缓存没有,取三级缓存的方法并执行生成带有代理的对象,存入二级缓存并注入到B。可以正常解决循环依赖并提前创建
  • 如果没有出现循环依赖 getBean(A)时,虽然也存入了三级缓存一个创建代理的方法,但是没有循环依赖所以没有再去bean容器查找,所以三级缓存相当于白存了,正常填充属性,再最后创建代理并返回即可

代码修改下 先定义一个创建代理的方法的接口

@FunctionalInterface
public interface ObjectFactory<T> {

	T getObject() throws BeansException;

}

bean容器中加入三级缓存,完整代买如下(省略未实现方法)

public class MySingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {

	/** bean容器,完整的bean,一级缓存 **/
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

	/** bean容器,不完整的bean,二级缓存 **/
	private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

	/** bean创建方法容器,存储不完整bean的创建方法,三级缓存 **/
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

	/** 存储正在创建的bean **/
	private final Set<String> singletonsCurrentlyInCreation =
			Collections.newSetFromMap(new ConcurrentHashMap<>(16));

	/**
	 * 查看bean是否正在创建
	 */
	public boolean isSingletonCurrentlyInCreation(String beanName) {
		return this.singletonsCurrentlyInCreation.contains(beanName);
	}

	/**
	 * 标志bean正在创建
	 */
	protected void beforeSingletonCreation(String beanName) {
		this.singletonsCurrentlyInCreation.add(beanName);
	}

	/**
	 * 标志bean创建完成
	 */
	protected void afterSingletonCreation(String beanName) {
		this.singletonsCurrentlyInCreation.remove(beanName);
	}

	/**
	 * 添加创建提前暴露bean的方法
	 */
	protected void addSingletonFactory(String beanName, ObjectFactory<?> objectFactory) {
		this.singletonFactories.put(beanName, objectFactory);
	}

	/** 添加bean **/
	@Override
	public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
		this.singletonObjects.put(beanName, singletonObject);
	}

	/** 获取bean **/
	@Override
	public Object getSingleton(String beanName) {
		return getSingleton(beanName, true);
	}

	public Object getSingleton(String beanName, Boolean allowEarlyReference) {
		// 一级缓存拿
		Object singletonObject = this.singletonObjects.get(beanName);
		// 如果拿不到并且正在创建,去二级缓存拿
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			singletonObject = this.earlySingletonObjects.get(beanName);
			// 二级缓存娶不到,三级缓存创建再存入二级缓存
			if (singletonObject == null && allowEarlyReference) {
				ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
				if (singletonFactory != null) {
					// 创建早器bean,包含代理的创建
					singletonObject = singletonFactory.getObject();
					// 这个还是不完整的bean存入二级缓存
					this.earlySingletonObjects.put(beanName, singletonObject);
				}
			}
		}
		return singletonObject;
	}
public class MyBeanFactory extends MySingletonBeanRegistry implements ConfigurableListableBeanFactory, BeanDefinitionRegistry {

	/** bean定义容器 **/
	private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

	/**
	 * 注册bean定义
	 */
	@Override
	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
		beanDefinitionMap.put(beanName, beanDefinition);
	}

	/**
	 * 获取bean定义
	 */
	@Override
	public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
		return this.beanDefinitionMap.get(beanName);
	}

	/**
	 * 提前初始化所有bean
	 * @throws BeansException
	 */
	@Override
	public void preInstantiateSingletons() throws BeansException {
		// 循环所有bean定义
		for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
			// 生产bean
			getBean(entry.getKey());
		}
	}

	/**
	 * 获取bean
	 */
	@Override
	public Object getBean(String name) throws BeansException {
		try {
			// 先去容器里拿
			Object singleton = getSingleton(name);
			// 如果没有就创建
			if (singleton==null) {
				// 标记正在创建
				beforeSingletonCreation(name);
				// 获取bean定义
				MyBeanDefinition beanDefinition = (MyBeanDefinition) getBeanDefinition(name);
				// 获取class
				Class<?> beanClass = beanDefinition.getBeanClass();
				// 实例化bean
				singleton = beanClass.newInstance();
				// 添加创建提前暴露bean的方法,包括代理
				Object finalSingleton = singleton;
				addSingletonFactory(name, ()-> createBeanProxy(finalSingleton, beanClass));
				// 填充属性
				popular(singleton, beanClass);
				// 看看有没有提前暴露
				Object singletonEarly = getSingleton(name, false);
				if (singletonEarly!=null) {
					singleton = singletonEarly;
				} else {
					// 创建代理
					System.out.println(name + " create proxy at last");
					singleton = createBeanProxy(finalSingleton, beanClass);
				}
				// 注册到容器
				registerSingleton(name, singleton);
				// 标记创建完成
				afterSingletonCreation(name);
			}
			return singleton;
		} catch (InstantiationException e) {
			return null;
		} catch (IllegalAccessException e) {
			return null;
		}
	}

	/**
	 * 填充属性
	 * @param singleton
	 * @param clazz
	 */
	private void popular(Object singleton, Class<?> clazz) {
		// 循环属性
		for (Field declaredField : clazz.getDeclaredFields()) {
			// 看看是否有MyAutowired注解
			MyAutowired annotation = declaredField.getAnnotation(MyAutowired.class);
			if (annotation!=null) {
				declaredField.setAccessible(true);
				try {
					// 属性赋值
					declaredField.set(singleton, getBean(declaredField.getType().getSimpleName()));
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * 模仿cglib创建代理,这里做了特殊处理,这种代理方式
	 * 实际上是给proxy对象增加一个target指向原对象,所以调用代理A的getB方法实际
	 * 上是调用A.target.getB方法。这样就解决了代理实际上没有注入属性的问题
	 * @param singleton
	 * @param clazz
	 * @return
	 */
	private Object createBeanProxy(Object singleton, Class<?> clazz) {
		Method[] Methods = clazz.getMethods();
		for (Method mth : Methods) {
			// 简化处理只代理一个
			if (mth.isAnnotationPresent(AopToString.class)) {
				Enhancer enhancer = new Enhancer();
				enhancer.setSuperclass(clazz);
				enhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> {
					if (method.equals(mth)) {
						System.out.print("TO String AOP ");
					}
					return method.invoke(singleton, objects);
				});
				return enhancer.create();
			}
		}
		return singleton;
	}

再加个没有循环依赖的BeanC

public class BeanC {
	public String cName = "C";

	@Override
	@AopToString
	public String toString() {
		return "{\"C\":{"
				+ "\"cName\":\""
				+ cName + '\"'
				+ "}}";

	}
}

测试

public class CircularApplication {
	public static void main(String[] args) {
		System.out.println("===factory===");
		MyBeanFactory myBeanFactory = new MyBeanFactory();
		myBeanFactory.registerBeanDefinition("BeanA", new MyBeanDefinition(BeanA.class));
		myBeanFactory.registerBeanDefinition("BeanB", new MyBeanDefinition(BeanB.class));
		myBeanFactory.registerBeanDefinition("BeanC", new MyBeanDefinition(BeanC.class));
		myBeanFactory.preInstantiateSingletons();
		Object a = myBeanFactory.getBean("BeanA");
		Object b = myBeanFactory.getBean("BeanB");
		Object c = myBeanFactory.getBean("BeanC");
		System.out.println(a);
		System.out.println(b);
		System.out.println(c);
	}
}

输出:

===factory===
BeanB create proxy at last
BeanC create proxy at last
TO String AOP {"A":{"aName":"A","b":B}}
{"BeanB":{"bName":"B","beanA":A}}
TO String AOP {"C":{"cName":"C"}}

可以看到,循环依赖没问题,代理没问题,而最后创建代理的只有BeanB和BeanC,BeanC就不用说了,没有循环依赖,A和B互相依赖,由于先创建A再B,B创建时已经可以获取到A的二级缓存了,所以B并不需要提前暴露。

有点绕,有空补个时序图吧 以上是BeanFactory的简单模拟,起名基本参照spring,但spring的源码肯定更复杂更多判断,比如代理是通过后置处理器实现的,但大体思路差不多 over~