手写Spring之BeanFactory(三级缓存)

概述

看了好久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实现的接口

DefaultListableBeanFactory

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

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

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

总结

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

BeanFactory

实现

之所以研究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 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 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 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 singletonObjects = new ConcurrentHashMap<>(256);

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

    /** 存储正在创建的bean **/
    private final Set 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 getObject() throws BeansException;

}

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

public class MySingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {

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

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

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

    /** 存储正在创建的bean **/
    private final Set 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 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 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~

你可能感兴趣的:(手写Spring之BeanFactory(三级缓存))