【spring】02详解spring框架的IOC

深入了解IOC

概念

IOC:控制反转

所谓控制,就是指资源的获取方式

主动式:

ExamServlet{
			ExamService es=new ExamService ();
			Paper paper=new Paper();// 复杂对象的创建是非常庞大的工程
}

被动式:

ExamServlet{
			Paper paper;
			public void test(){
				paper.checkout();
			}
}

简单总结:控制反转就是把创建和管理bean的过程交给了第三方,而这里的第三方就是容器Spring IoC Container

bean是什么?
Bean就是包装好了的对象,无论依赖注入还是控制反转都是针对bean来说的。

容器是什么
容器:管理所有的组件(有功能的类),负责创建配置和管理bean。

因为对象的创建和销毁都是很麻烦的,让容器去管理对象的声明,我们只管使用就可以了

假设ExamServlet受容器管理,ExamService 也受容器管理;容器可以自动的探查出哪些组件(类)需要用到另一些组件(类);容器帮我们创建ExamService 对象,并把ExamService 对象赋值

容器:主动的new资源变为被动的接受资源;容器可以理解为是婚介所;找对象的人由主动获取变为被动接受;
在这里插入图片描述
IOC容器
Spring 提供了两种 IoC 容器,分别是 BeanFactory、ApplicationContext 。

BeanFactory ,就像一个包含 Bean 集合的工厂类。它会在客户端要求时实例化 Bean 对象。
ApplicationContext,它是 BeanFactory 的子类,更好的补充并实现了 BeanFactory 的。

ApplicationContext 的里面有两个具体的实现子类,用来读取配置配件的:

  • ClassPathXmlApplicationContext - 从 class path 中加载配置文件,更常用一些;
  • FileSystemXmlApplicationContext - 从本地文件中加载配置文件,不是很常用,如果再到 Linux 环境中,还要改路径,不是很方便。
  • XmlWebApplicationContext :由 Web 应用的XML文件读取上下文。例如我们在 Spring MVC 使用的情况。

DI(Dependency injection)依赖注入
容器能知道哪个组件类运行的时候,需要另外一个类(组件);容器通过反射的形式,将容器中准备好的ExamService 对象,注入(利用反射给属性赋值)到BookServlet中;

主要是容器管理的组件,都能使用容器提供的强大功能

通过各种方式给容器中注册对象,所以前是自己new对象吗,现在所有的对象交给容器创建,给容器中注册组件,就像是国家负责分配对象一样,不用自己找对象了,你需要什么样的对象,国家给你安排,依赖注入就是给你找的对象指定指标,指定多高多胖等等的属性
在这里插入图片描述

spring IOC 的实现机制

spring ioc就是通过工厂+反射实现的,demo如下

interface Fruit {

     public abstract void eat();
     
}
class Apple implements Fruit {

    public void eat(){
        System.out.println("Apple");
    }
    
}
class Orange implements Fruit {
    public void eat(){
        System.out.println("Orange");
    }
}

class Factory {
    // 具体实现的工厂
    public static Fruit getInstance(String className) {
        Fruit f = null;
        try {
            f = (Fruit) Class.forName(className).newInstance(); // 反射机制动态获取类中的信息
        } catch (Exception e) {
            e.printStackTrace();
        }
        return f;
    }
    
}

class Client {

    public static void main(String[] args) {
        Fruit f = Factory.getInstance("io.github.dunwu.spring.Apple");
        if(f != null){
            f.eat();
        }
    }
    
}

上面的小例子就是在运行的时候才把io.github.dunwu.spring.Apple传进去,工厂才知道生产哪个类,可以把io.github.dunwu.spring.Apple变成变量,然后写入配置文件,就可以根据需求动态的决定生产哪个类,这个例子就体现了ioc生产bean的思想。

使用spring框架

使用框架一般都分为三步:1.引入依赖;2.修改配置文件;3.测试
导包
4个核心jar包
在这里插入图片描述
日志包
在这里插入图片描述
写配置
集合了spring的ioc容器管理的所有组件(类)
创建一个Spring Bean Configuration

实例测试

新建Person类
在这里插入图片描述
配置文件
在这里插入图片描述
测试类
在这里插入图片描述

分析

1.对象是什么时候创建的?

在类的构造方法中打印什么时候调用,在类的getter、setter方法打印什么时候调用,然后再容器启动后打印启动完成,就可以知道对象是什么时候创建的
在这里插入图片描述
可以看出在容器启动完成之前,对象已经创建了,并且已经赋值,而且容器是通过类的构造函数创建对象,通过类的getter,setter方法赋值。

2.创建对象是否是单例模式

从容器中取出id为01的创建好的对象在这里插入图片描述
判断是否相等
在这里插入图片描述
结果是相等
在这里插入图片描述
说明容器只创建了一次对象,是单例模式

3.获取不存在的对象,就会报异常

org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named ‘person03’ available
在这里插入图片描述
执行结果
在这里插入图片描述

4.只要容器一启动所有的对象都创建了
在这里插入图片描述
可以看出构造函数调用了两次,一共有两个对象都创建出来了

小结

  • 结论
    • 给容器中创建一个组件,我们根据id拿到对象
    • 容器创建之后对象就创建了
    • 只要容器一启动所有的对象都创建了
    • 同一组件在ioc中是单实例的,容器启动完成之前都已经创建准备好的
    • 如果获取容器中没有的组件,获取组件就会报异常
    • ioc容器在创建这个组件对象的时候,property会利用setter方法为javaBean属性进行赋值
    • src 源码包开始的路径,称为类路径的开始
    • 所有源码包里面的都会被合并放在类路径里面

猜你喜欢

转载自blog.csdn.net/yujing1314/article/details/106903177
今日推荐