什么是Spring的IoC,依赖注入又该怎么实现?

关注“Java架构栈”微信公众号,回复暗号【Java面试题】即可获取大厂面试题

 什么是IoC

所谓的控制反转(Inversion of Control),缩写为IoC,其实就是把对象的创建和对象之间的依赖关系处理,交给 Spring容器来管理,不用程序员自己创建和维护的一种技术。我们使用IoC的目的,主要是为了降低类之间的耦合。

 IoC的底层原理

IoC的底层原理主要是基于xml解析+工厂模式+反射等技术进行实现。

  • xml解析:基于xml,配置好要创建的Javabean对象;

  • 工厂模式:把对类的创建初始化等工作,全都交给一个工厂来执行;

  • 反射:使用反射技术创建xml中配置的bean。

 IoC模拟实现

为了让大家更好地理解IoC的工作原理,接下来我们自己简单模拟一下Spring IoC的底层实现原理。

第一步:我们先准备一个属性文件beans.properties,我这里使用属性文件代替xml的文件功能。

dept=com.qfedu.pojo.Dept
emp=com.qfedu.pojo.Emp

第二步:编写工厂类QfBeanFactory.java

/**
* 模拟spring 容器的工厂类
*/
public class QfBeanFactory {
    private static Properties properties = new Properties();
    //该map相当于spring容器,用来存储创建好的bean对象
    private static Map<String, Object> ioc = new HashMap<String, Object>();
    static {
        try {
            properties.load(BeanFactory.class.getClassLoader().getResourceAsStream("beans.properties"));
            //获取所有属性名
            Set<String> names = properties.stringPropertyNames();
            System.out.println(names);
            //通过反射技术创建属性文件里配置的要创建的bean开始
            for (String name : names) {
                //获取全类名
                String clsName= (String) properties.get(name);
                Class clazz=Class.forName(clsName);
                if (!Objects.isNull(clazz)){
                    //反射构建对象
                   Object object=clazz.getConstructor().newInstance();
                   // 存储到map中
                   ioc.put(name,object);
                }
            }
         //通过反射技术创建属性文件里配置的要创建的bean结束
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
       通过属性文件中属性名(类似spring配置文件中的bean的id)获取工厂创建好的对象
    */
    public  static Object getBean(String beanName){
        return ioc.get(beanName);
    }
}

代码解释:

  • 工厂类中的静态代码块实现读取属性文件中的配置信息;

  • 根据读到的配置信息,使用反射技术构建bean对象;

  • 然后将构建好的对象放到map中;

  • 通过提供的getBean方法,获取工厂中创建好的bean对象。

第三步:我们再编写一个测试类:

public class IocTest{
  public static void main(String[] args) {
      Dept dept= (Dept)QfBeanFactory.getBean("dept");
      System.out.println(dept);
      Emp emp= (Emp)QfBeanFactory.getBean("emp");
      System.out.println(emp);
    }
}

经过以上测试我们可以获得创建好的dept和emp对象,以上我们模拟了spring ioc的原理。

 bean对象的创建

接下来我们再来看看Spring框架又是怎么创建和使用bean对象的。

4.1 创建spring-bean.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

       xsi:schemaLocation="http://www.springframework.org/schema/beans

        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="dept" class="com.qfedu.pojo.Dept"></bean>

    <bean id="emp" class="com.qfedu.pojo.Emp"></bean>

</beans>

4.2 加载配置文件获得Spring IoC容器

ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring-bean.xml");

4.3 通过spring容器获取dept、emp 对象

Emp emp= (Emp) applicationContext.getBean("emp");
System.out.println(emp);
Dept dept= (Dept) applicationContext.getBean("dept");
System.out.println(dept);

4.4 小结

最后我们再总结一下Spring创建bean对象的过程。

  • spring-bean.xml相当于

    beans.properties;

  • ClassPathXmlApplicationContext就相当于QfBeanFactory;

  • getBean 方法相当于QfBeanFactory中的getBean。

其中ClassPathXmlApplicationContext类的结构图如下所示:

通过以上类结构图,我们可以看出ClassPathXmlApplicationContext的最顶层就是BeanFacorty工厂,而ClassPathXmlApplicationContext则是一个具体的实现类。BeanFacorty有很多实现类,其中ClassPathXmlApplicationContext、AnnotationConfigApplicationContext则是比较常用的具体子类。

BeanFactory以Factory结尾,表示这是一个工厂类(接口), 它负责生产和管理bean的一个工厂。在Spring中,BeanFactory是IOC容器的核心接口,它的职责包括实例化、定位、配置应用程序中的对象及建立这些对象间的依赖等。BeanFactory只是个接口,并不是IoC容器的具体实现,所以Spring容器给出了多种实现,如 ClassPathXmlApplicationContext、AnnotationConfigApplicationContext、ApplicationContext等。

现在你知道Spring是怎么实现IoC的了吗?如果你还有什么疑问,可以在评论区留言哦。关注Java架构栈,干货天天都不断哦!

猜你喜欢

转载自blog.csdn.net/weixin_41692221/article/details/131434907