周末肝一个丐版 Spring IOC 容器

620 阅读10分钟

IOC(Inversion of Control)控制反转作为Spring的核心思想,在Spring框架中,最核心的概念就是容器,IOC容器是Spring实现IOC的载体,它其实就是一个大工厂,用来管理我们所有的对象以及依赖关系。

  • 原理就是通过Java反射技术来实现。
  • 通过配置文件或注解来描述类之间的依赖关系。
  • 通过配置和反射技术来构建对象和依赖关系。

Spring提供了两种不同类型的容器:

  • 最基础、面向Spring框架的BeanFactory。
  • 高级的、基于 BeanFactory基础之上、面向开发者的ApplicationContext。

简单实现IOC容器

原理:基于反射技术与工厂模式。

基于XML配置文件实现

核心流程

  • 初始化IOC容器。
  • 读取配置文件,提取节点。
  • 将映射为BeanDefinition,注册到 beanDefinitionMap。
  • 将 beanDefinitionMap 中所有的 BeanDefinition 实例化 Bean 对象。
  • 设置属性,注入对象之间的依赖关系。

不扯干的,直接上代码,代码就是越肝越爽,肝了,先实现一个丐版吧!!!

pom

<dependencies>
    <dependency>
        <groupId>dom4j</groupId>
        <artifactId>dom4j</artifactId>
        <version>1.6.1</version>
    </dependency>
    <dependency>
        <groupId>jaxen</groupId>
        <artifactId>jaxen</artifactId>
        <version>1.2.0</version>
    </dependency>
    <dependency>
        <groupId>commons-lang</groupId>
        <artifactId>commons-lang</artifactId>
        <version>2.6</version>
    </dependency>
</dependencies>

ApplicationContext

public interface ApplicationContext {

    public Object getBean(String beanName);

    public Object createBean(BeanDefinition beanDefinition);
}

BeanDefinition

public class BeanDefinition {
    private String beanName;
    private String className;
    private Class beanClass;
    private List<Property> properties = new ArrayList<Property>();

    public BeanDefinition(){

    }
    public BeanDefinition(String beanName, String  className){
        this.beanName = beanName;
        this.className = className;
    }

    public String getBeanName() {
        return beanName;
    }

    public void setBeanName(String beanName) {
        this.beanName = beanName;
    }

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }


    public List<Property> getProperties() {
        return properties;
    }

    public void setProperties(List<Property> properties) {
        this.properties = properties;
    }

    public Class getBeanClass() {
        return beanClass;
    }

    public void setBeanClass(Class beanClass) {
        this.beanClass = beanClass;
    }
}

Property

public class Property {

    private String name;
    private String value;
    private String ref;

    public Property(String name, String value, String ref) {
        this.name = name;
        this.value = value;
        this.ref = ref;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    public String getRef() {
        return ref;
    }

    public void setRef(String ref) {
        this.ref = ref;
    }
}

ClassPathXmlApplicationContext

public class ClassPathXmlApplicationContext implements ApplicationContext {

    private String configLocation;

    private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<String, BeanDefinition>() ;

    private Map<String, Object> iocMap = new HashMap<String, Object>();


    public ClassPathXmlApplicationContext(String configLocation){
        this.configLocation = configLocation;
        parseXmlFile();
        if(!beanDefinitionMap.isEmpty()){
            for(Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()){
                String id = entry.getKey();
                //在依赖注入的时候,部分bean可能会提前已创建
                if(!iocMap.containsKey(id)){
                    BeanDefinition bean = entry.getValue();
                    createBean(bean);
                }
            }
        }
    }

    public Object getBean(String beanName) {
        BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
        if(null == beanDefinition){
            throw new RuntimeException("no beanDefinition : " + beanName);
        }
        Object object = iocMap.get(beanName);
        if(null != object){
            return object;
        } else {
            return createBean(beanDefinition);
        }
    }

    public Object createBean(BeanDefinition bean){
        Object object = null;
        Class cls = null;
        String beanName = bean.getBeanName();
        String className = bean.getClassName();
        List<Property> properties = bean.getProperties();
        System.out.println("["+beanName+"] create start>>>>");
        //反射生成Class对象
        try {
            cls = Class.forName(className);
            System.out.println("["+beanName+"] class >> :" + cls.toString());
            bean.setBeanClass(cls);
        } catch (Exception e) {
            throw new RuntimeException("reflex class fail:["+beanName+"]" + "\n" +ExceptionUtils.getStackTrace(e));
        }
        try {
            object = cls.newInstance();
        } catch (Exception e) {
            throw new RuntimeException("class instance fail:["+beanName+"]" + "\n" +ExceptionUtils.getStackTrace(e));
        }
        //设置属性
        if(!properties.isEmpty()){
            for(Property property:properties){
                //value注入
                if(property.getValue() != null){
                    Method setterMethod = BeanUtils.getSetterMethod(object, property.getName());
                    try{
                        setterMethod.invoke(object, property.getValue());
                        System.out.println("["+beanName+"] set value >> " + property.getName() + ":" + property.getValue());
                    }catch (Exception e){
                        throw new RuntimeException("set value fail:["+beanName+"."+property.getName() +"]" + "\n" +ExceptionUtils.getStackTrace(e));
                    }
                }
                //依赖注入
                if(property.getRef() != null){
                    Method setterMethod = BeanUtils.getSetterMethod(object, property.getName());
                    Object refObj = getBean(property.getRef());
                    if(refObj == null){
                        throw new RuntimeException("set ref fail:["+property.getRef()+"] is null");
                    }
                    try{
                        setterMethod.invoke(object, refObj);
                        System.out.println("["+beanName+"] set DI >> " + property.getName() + ":" + refObj.toString());
                    }catch (Exception e){
                        throw new RuntimeException("set ref fail:["+beanName+"."+property.getRef() +"] " + "\n" +ExceptionUtils.getStackTrace(e));
                    }
                }
            }
        }
        System.out.println("["+beanName+"] end>> :" + object.toString());
        iocMap.put(beanName, object);
        return object;
    }

    /**
     * 解析xml文件
     * @return
     */
    private void parseXmlFile(){
        Document document = null;
        SAXReader reader = new SAXReader();
        InputStream inputStream = ClassPathXmlApplicationContext.class.getResourceAsStream(configLocation);
        try {
            document = reader.read(inputStream);
        } catch (DocumentException e) {
            throw new RuntimeException("read xml file fail:" + "\n" +ExceptionUtils.getStackTrace(e));
        }
        List<Element> elementList = document.selectNodes("//bean");
        if(!elementList.isEmpty()){
            // 遍历所有bean节点
            for(Element element : elementList){
                String id = element.attributeValue("id");
                if(beanDefinitionMap.containsKey(id)){
                    throw new RuntimeException("bean already exists: " + id);
                }
                String className = element.attributeValue("class");
                BeanDefinition bean = new BeanDefinition(id, className);
                //遍历bean下所有property属性节点
                List<Element> properties= element.elements("property");
                if(!properties.isEmpty()){
                    for(Element pElement : properties){
                        String name  = pElement.attributeValue("name");
                        String value = pElement.attributeValue("value");
                        String ref = pElement.attributeValue("ref");
                        Property property = new Property(name, value, ref);
                        bean.getProperties().add(property);
                    }
                }
                beanDefinitionMap.put(id, bean);
            }
        }
    }
}

BeanUtils

public class BeanUtils
{

    /** * 匹配setter方法的正则表达式 */
    private static final Pattern SET_PATTERN = Pattern.compile("set(\p{javaUpperCase}\w*)");


    /**
     * 获取对象的setter方法。
     */
    public static Method getSetterMethod(Object obj, String property)
    {
        Method[] methods = obj.getClass().getMethods();
        for (Method method : methods)
        {
            Matcher m = SET_PATTERN.matcher(method.getName());
            if (m.matches() && (method.getParameterTypes().length == 1))
            {
                if(method.getName().toLowerCase().equals(("set" + property).toLowerCase())){
                    return method;
                }
            }
        }
        return null;
    }
}

基于注解实现

@Autowired

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {
}

@Component

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Component {
}

@Service

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Service {
}

@ComponentScan

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ComponentScan {
    String basePackage() default "";
}

@Value

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Value {
    String value();
}

AnnotationConfigApplicationContext

public class AnnotationConfigApplicationContext implements ApplicationContext {

    private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<String, BeanDefinition>();

    private Map<String, Object> iocMap = new HashMap<String, Object>();

    private  final Class<?> configClass;

    public AnnotationConfigApplicationContext(Class<?> configClass) {
        this.configClass = configClass;
        scanPackageClass();
        if(!beanDefinitionMap.isEmpty()){
            for(Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()){
                String id = entry.getKey();
                //在依赖注入的时候,部分bean可能会提前已创建
                if(!iocMap.containsKey(id)){
                    BeanDefinition bean = entry.getValue();
                    createBean(bean);
                }
            }
        }

    }

    /**
     * 扫描所有注解
     */
    private void scanPackageClass(){
        if(!configClass.isAnnotationPresent(ComponentScan.class)){
            return;
        }
        //获取注解中的扫描路径
        String basePackage = configClass.getDeclaredAnnotation(ComponentScan.class).basePackage();
        List<Class<?>> classes = ClassUtils.getClasses(basePackage);
        for(Class<?> cls : classes){
            BeanDefinition beanDefinition =  new BeanDefinition();
            //@Component或@Service
            if(cls.isAnnotationPresent(Component.class) || cls.isAnnotationPresent(Service.class)){
                String beanName = cls.getSimpleName();;
                //如果注解是@Service并且实现了接口,则取第一个接口为name
                if(cls.isAnnotationPresent(Service.class) && cls.getInterfaces().length>0){
                    beanName = cls.getInterfaces()[0].getSimpleName();
                }
                beanName = ClassUtils.toLowerCaseFirstOne(beanName);//首字母小写
                String className = cls.getName();
                beanDefinition.setBeanClass(cls);
                beanDefinition.setBeanName(beanName);
                beanDefinition.setClassName(className);
                if(beanDefinitionMap.containsKey(beanName)){
                    throw new RuntimeException("bean already exists: " + beanName);
                }
                beanDefinitionMap.put(beanName, beanDefinition);
            }
        }

    }

    public Object getBean(String beanName) {
        BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
        if(null == beanDefinition){
            throw new RuntimeException("no beanDefinition : " + beanName);
        }
        Object object = iocMap.get(beanName);
        if(null != object){
            return object;
        } else {
            return createBean(beanDefinition);
        }
    }

    public Object createBean(BeanDefinition beanDefinition) {
        Class<?> beanClass = beanDefinition.getBeanClass();
        String beanName = beanDefinition.getBeanName();
        System.out.println("["+beanName+"] create start>>>>");
        Object object = null;
        // 实例化
        try {
            object = beanClass.newInstance();
        } catch (Exception e) {
            throw new RuntimeException("class instance fail:["+ beanName +"]" + "\n" + ExceptionUtils.getStackTrace(e));
        }

        for(Field field: beanClass.getDeclaredFields()){
            //属性赋值
            if(field.isAnnotationPresent(Value.class)){
                Value valueAnnotation = field.getAnnotation(Value.class);
                String value = valueAnnotation.value();
                //属性的setter方法
                Method setterMethod = BeanUtils.getSetterMethod(object, field.getName());
                Object val = null;
                switch (field.getType().getName()){
                    case "java.lang.Integer":
                        val = Integer.parseInt(value);
                        break;
                    case "java.lang.String":
                        val = value;
                        break;
                    case "java.lang.Float":
                        val = Float.parseFloat(value);
                        break;
                }
                try {
                    setterMethod.invoke(object, val);
                    System.out.println("["+beanName+"] set value >> " + field.getName() + ":" + val);
                } catch (Exception e) {
                    throw new RuntimeException("set value fail:[" + beanName + "." + field.getName() +"] " + "\n" +ExceptionUtils.getStackTrace(e));
                }
            }

            //依赖注入:@Autowired
            if(field.isAnnotationPresent(Autowired.class)){
                Object ref = getBean(field.getName());
                if(ref == null){
                    throw new RuntimeException("set ref fail:["+field.getName()+"] is null");
                }
                field.setAccessible(true);
                try {
                    field.set(object, ref);
                    System.out.println("["+beanName+"] set DI >> " + field.getName() + ":" + ref.toString());
                } catch (IllegalAccessException e) {
                    throw new RuntimeException("set ref fail:["+ beanName +"."+ field.getName() +"] " + "\n" +ExceptionUtils.getStackTrace(e));
                }
            }
        }
        iocMap.put(beanDefinition.getBeanName(), object);
        return object;
    }
}

ClassUtils

public class ClassUtils {

    /**
     * 从包package中获取所有的Class
     *
     * @param packageName
     * @return
     */
    public static List<Class<?>> getClasses(String packageName) {

        // 第一个class类的集合
        List<Class<?>> classes = new ArrayList<Class<?>>();
        // 是否循环迭代
        boolean recursive = true;
        // 获取包的名字 并进行替换
        String packageDirName = packageName.replace('.', '/');
        // 定义一个枚举的集合 并进行循环来处理这个目录下的things
        Enumeration<URL> dirs;
        try {
            dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
            // 循环迭代下去
            while (dirs.hasMoreElements()) {
                // 获取下一个元素
                URL url = dirs.nextElement();
                // 得到协议的名称
                String protocol = url.getProtocol();
                // 如果是以文件的形式保存在服务器上
                if ("file".equals(protocol)) {
                    // 获取包的物理路径
                    String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
                    // 以文件的方式扫描整个包下的文件 并添加到集合中
                    findAndAddClassesInPackageByFile(packageName, filePath, recursive, classes);
                } else if ("jar".equals(protocol)) {
                    // 如果是jar包文件
                    // 定义一个JarFile
                    JarFile jar;
                    try {
                        // 获取jar
                        jar = ((JarURLConnection) url.openConnection()).getJarFile();
                        // 从此jar包 得到一个枚举类
                        Enumeration<JarEntry> entries = jar.entries();
                        // 同样的进行循环迭代
                        while (entries.hasMoreElements()) {
                            // 获取jar里的一个实体 可以是目录 和一些jar包里的其他文件 如META-INF等文件
                            JarEntry entry = entries.nextElement();
                            String name = entry.getName();
                            // 如果是以/开头的
                            if (name.charAt(0) == '/') {
                                // 获取后面的字符串
                                name = name.substring(1);
                            }
                            // 如果前半部分和定义的包名相同
                            if (name.startsWith(packageDirName)) {
                                int idx = name.lastIndexOf('/');
                                // 如果以"/"结尾 是一个包
                                if (idx != -1) {
                                    // 获取包名 把"/"替换成"."
                                    packageName = name.substring(0, idx).replace('/', '.');
                                }
                                // 如果可以迭代下去 并且是一个包
                                if ((idx != -1) || recursive) {
                                    // 如果是一个.class文件 而且不是目录
                                    if (name.endsWith(".class") && !entry.isDirectory()) {
                                        // 去掉后面的".class" 获取真正的类名
                                        String className = name.substring(packageName.length() + 1, name.length() - 6);
                                        try {
                                            // 添加到classes
                                            classes.add(Class.forName(packageName + '.' + className));
                                        } catch (ClassNotFoundException e) {
                                            e.printStackTrace();
                                        }
                                    }
                                }
                            }
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return classes;
    }

    /**
     * 以文件的形式来获取包下的所有Class
     *
     * @param packageName
     * @param packagePath
     * @param recursive
     * @param classes
     */
    public static void findAndAddClassesInPackageByFile(String packageName, String packagePath, final boolean recursive,
                                                        List<Class<?>> classes) {
        // 获取此包的目录 建立一个File
        File dir = new File(packagePath);
        // 如果不存在或者 也不是目录就直接返回
        if (!dir.exists() || !dir.isDirectory()) {
            return;
        }
        // 如果存在 就获取包下的所有文件 包括目录
        File[] dirfiles = dir.listFiles(new FileFilter() {
            // 自定义过滤规则 如果可以循环(包含子目录) 或则是以.class结尾的文件(编译好的java类文件)
            public boolean accept(File file) {
                return (recursive && file.isDirectory()) || (file.getName().endsWith(".class"));
            }
        });
        // 循环所有文件
        for (File file : dirfiles) {
            // 如果是目录 则继续扫描
            if (file.isDirectory()) {
                findAndAddClassesInPackageByFile(packageName + "." + file.getName(), file.getAbsolutePath(), recursive,
                        classes);
            } else {
                // 如果是java类文件 去掉后面的.class 只留下类名
                String className = file.getName().substring(0, file.getName().length() - 6);
                try {
                    // 添加到集合中去
                    classes.add(Class.forName(packageName + '.' + className));
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    // 首字母转小写
    public static String toLowerCaseFirstOne(String s) {
        if (Character.isLowerCase(s.charAt(0)))
            return s;
        else
            return (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString();
    }
}

跑起来看看

A

import com.syun.spring.ioc.core.annotation.Autowired;
import com.syun.spring.ioc.core.annotation.Component;
import com.syun.spring.ioc.core.annotation.Value;

@Component
public class A {

    @Value(value = "a-1")
    private String a1;
    @Value(value = "a-2")
    private String a2;
    @Value(value = "a-3")
    private String a3;

    @Autowired
    private B b;

    public B getB() {
        return b;
    }

    public void setB(B b) {
        this.b = b;
    }

    public String getA1() {
        return a1;
    }

    public void setA1(String a1) {
        this.a1 = a1;
    }

    public String getA2() {
        return a2;
    }

    public void setA2(String a2) {
        this.a2 = a2;
    }

    public String getA3() {
        return a3;
    }

    public void setA3(String a3) {
        this.a3 = a3;
    }

    @Override
    public String toString() {
        return "A{" +
                "a1='" + a1 + ''' +
                ", a2='" + a2 + ''' +
                ", a3='" + a3 + ''' +
                ", b=" + b +
                '}';
    }
}

B

import com.syun.spring.ioc.core.annotation.Component;
import com.syun.spring.ioc.core.annotation.Value;

@Component
public class B {

    @Value(value = "b-1")
    private String b1;
    @Value(value = "b-2")
    private String b2;
    @Value(value = "b-3")
    private String b3;

    public String getB1() {
        return b1;
    }

    public void setB1(String b1) {
        this.b1 = b1;
    }

    public String getB2() {
        return b2;
    }

    public void setB2(String b2) {
        this.b2 = b2;
    }

    public String getB3() {
        return b3;
    }

    public void setB3(String b3) {
        this.b3 = b3;
    }

    @Override
    public String toString() {
        return "B{" +
                "b1='" + b1 + ''' +
                ", b2='" + b2 + ''' +
                ", b3='" + b3 + ''' +
                '}';
    }
}

UserService

public interface UserService {
    void getUserInfo();
}

UserServiceImpl

import com.syun.service.UserService;
import com.syun.spring.ioc.core.annotation.Service;

@Service
public class UserServiceImpl implements UserService {
    public void getUserInfo() {
        System.out.println("name:shiyunxi,age:22");
    }
}

application.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans>
    <bean id="userService" class="com.syun.service.impl.UserServiceImpl"></bean>

    <bean id="a" class="com.syun.entry.A">
        <property name="a1" value="shiyunxi"></property>
        <property name="a2" value="男"></property>
        <property name="b" ref="b"></property>
    </bean>
    <bean id="b" class="com.syun.entry.B">
        <property name="b1" value="2018"></property>
        <property name="b2" value="12"></property>
        <property name="b3" value="8"></property>
    </bean>
</beans>

XmlTest

public class XmlTest {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/application.xml");
        A a = (A) applicationContext.getBean("a");
        System.out.println(a.toString());
        UserService userService = (UserService) applicationContext.getBean("userService");
        userService.getUserInfo();
    }
}

AnnotationTest

@ComponentScan(basePackage = "com.syun")
public class AnnotationTest {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AnnotationTest.class);
        A a = (A) applicationContext.getBean("a");
        System.out.println(a.toString());
        UserService userService = (UserService) applicationContext.getBean("userService");
        userService.getUserInfo();
    }
}


循环依赖

上面的IOC容器还存在一个棘手的问题,循环依赖。

Spring如何解决循环依赖

Spring解决循环依赖的理论依据是基于Java的引用传递,当我们获取到对象的引用时,对象的属性是可以延迟设置的。Spring的单例对象的初始化主要分为三步:

  • 实例化:调用对象的构造方法实例化对象。
  • 属性赋值:填充属性。
  • 初始化:属性注入后,执行自定义初始化。

循环依赖主要发生在实例化、注入,存在构造器循环依赖和属性注入依赖。

Spring为了解决单例的循环依赖问题,使用了三级缓存。

	/** Cache of singleton objects: bean name --> bean instance */
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

	/** Cache of singleton factories: bean name --> ObjectFactory */
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

	/** Cache of early singleton objects: bean name --> bean instance */
	private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
  • 第一级缓存 singletonObjects:存放了已实例化、初始化的完成的Bean对象。
  • 第二级缓存 earlySingletonObjects:存放了已实例化、未属性赋值的半成品的Bean对象。
  • 第三级缓存 singletonFactories:存放可以生成Bean的工厂。

为么使用三级缓存

① 使用一级缓存

  • 实例化A,将半成品的A放到一级缓存中,发现需要B,再去实例化B。
  • 实例化B过程中发现需要A,于是从一级缓存中取出A(半成品),完成B的创建,将B加入一级缓存。
  • 继续创建A,从一级缓存拿到B,填充到A的属性中,完成A的创建。

存在问题:基本流程下,是可以解决循环依赖的,但是在创建过程中,当另一个线程取A,可能会出现拿到化的半成品的A。

② 使用二级缓存

一级缓存:存放已实例化和初始化的 Bean。

二级缓存:存放已实例化未属性赋值的Bean(半成品)。

  • 实例化A,将半成品的A放到二级缓存,发现需要B,再去实例化B。
  • 实例化B,将半成品的B放到二级缓存,创建过程中发现需要A,于是B先查一级缓存,没有,再查二级缓存,找到A后,完成B的创建,将B加入一级缓存,并删除二级缓存的B。
  • 继续创建A,从一级缓存拿到B,填充到A的属性中,完成A的创建,将A放到一级缓存,并删除二级缓存中的A。

存在问题:这个流程保证了线程安全,如果A有AOP的话,因为二级缓存存放的是原始对象,而我们需要注入A的代理对象,这样的话就满足不了代理需求。

③ 使用三级缓存

三级缓存 缓存的是ObjectFactory , 也就是一个Lambda表达式,主要是为了生成代理对象。如果当前Bean需要AOP , 那么执行完lambda之后得到的就是一个代理对象 ,如果无需AOP , 那就是原始对象。

  • 实例化A的过程中需要B,先将A放到三级缓存里面,再去实例化B。
  • 实例化B的过程中发现需要A,于是B先查一级缓存,没有,再查二级缓存,还没有,再查三级缓存,找到了A后,把A放到二级缓存,并删除三级缓存中的A。
  • B初始化完成后,将B放到一级缓存,此时B里面的A还是创建中状态,继续创建A,直接从一级缓存里面拿到B,完成A的初始化,并将A放到一级缓存中,删除二级缓存的A。

简单解决循环依赖

下面通过一级缓存和二级缓存两种方式,简单解决循环依赖问题,基于AnnotationConfigApplicationContext 代码优化。

① 使用一级缓存

改动比较小,只是在实例化的时候,将object保存到缓存中。

② 使用二级缓存

public Object getSingletonObject(String beanName){
        /**
         * 1.先从一级缓存获取。
         * 2.当从一级缓存获取不到,则从二级缓存获取。
         */
        BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
        if(null == beanDefinition){
            throw new RuntimeException("no beanDefinition : " + beanName);
        }
        Object object = singletonObjects.get(beanName);
        if(object == null){
            object = earlySingletonObjects.get(beanName);
            if(object == null){
                object = createBean(beanDefinition);
            }
        }
        return object;
    }
public Object createBean(BeanDefinition beanDefinition) {
        Class<?> beanClass = beanDefinition.getBeanClass();
        String beanName = beanDefinition.getBeanName();
        System.out.println("["+beanName+"] create start>>>>");
        Object object = null;
        // 实例化
        try {
            object = beanClass.newInstance();
            //将半成品存放到二级缓存
            earlySingletonObjects.put(beanName, object);
            System.out.println("["+beanName+"] 半成品保存到二级缓存");
        } catch (Exception e) {
            throw new RuntimeException("class instance fail:["+ beanName +"]" + "\n" + ExceptionUtils.getStackTrace(e));
        }

        for(Field field: beanClass.getDeclaredFields()){
            //属性赋值
            if(field.isAnnotationPresent(Value.class)){
                Value valueAnnotation = field.getAnnotation(Value.class);
                String value = valueAnnotation.value();
                //属性的setter方法
                Method setterMethod = BeanUtils.getSetterMethod(object, field.getName());
                Object val = null;
                switch (field.getType().getName()){
                    case "java.lang.Integer":
                        val = Integer.parseInt(value);
                        break;
                    case "java.lang.String":
                        val = value;
                        break;
                    case "java.lang.Float":
                        val = Float.parseFloat(value);
                        break;
                }
                try {
                    setterMethod.invoke(object, val);
                    System.out.println("["+beanName+"] set value >> " + field.getName() + ":" + val);
                } catch (Exception e) {
                    throw new RuntimeException("set value fail:[" + beanName + "." + field.getName() +"] " + "\n" +ExceptionUtils.getStackTrace(e));
                }
            }

            //依赖注入:@Autowired
            if(field.isAnnotationPresent(Autowired.class)){
                //从缓存获取bean
                Object ref = getSingletonObject(field.getName());
                if(ref == null){
                    throw new RuntimeException("set ref fail:["+field.getName()+"] is null");
                }
                field.setAccessible(true);
                try {
                    field.set(object, ref);
                    System.out.println("["+beanName+"] set DI >> " + field.getName() + ":" + ref.toString());
                } catch (IllegalAccessException e) {
                    throw new RuntimeException("set ref fail:["+ beanName +"."+ field.getName() +"] " + "\n" +ExceptionUtils.getStackTrace(e));
                }
            }
        }
        System.out.println("["+beanName+"] end >> :" + object.toString());
        // 将完整的bean保存到一级缓存,并且删除二级缓存
        singletonObjects.put(beanName, object);
        earlySingletonObjects.remove(beanName);
        System.out.println("["+beanName+"] 完整版保存到一级缓存,并删除二级缓存");
        return object;
    }


实现过程中也参考了不少优秀的博客,在此就不贴啦,附上我的gitee地址吧。

gitee.com/renxiaoshi/…