Spring IOC

Spring IOC

什么是IOC

IOC的全称叫Inversion Of Control (控制反转),是一种对象注入技术,用于实现组件之间的解耦和依赖关系的管理。

在传统的面向对象编程中,对象之间通常是通过直接创建和调用其他对象来实现相互依赖的。这种依赖关系是编码时静态确定的,因此对于对象之间的复杂依赖关系的管理往往比较困难。而IoC则将对象之间的依赖关系交给Spring容器来管理,在运行时动态地注入对象之间的依赖关系,从而实现对象之间的松耦合和灵活性。

在Spring中,IoC是通过IOC容器实现的。IoC容器负责实例化、配置、组装和管理Spring应用程序中的对象。它使用依赖注入(Dependency Injection,DI)将对象之间的依赖关系动态地注入到相关的对象中,从而实现对象之间的低耦合度。这样,对象之间的依赖关系将由容器在运行时来管理,而不是由开发者在编写代码时静态地确定。

在传统的程序开发中,当需要调用对象时,通常由调用者来创建被调用者的实例,即对象室友调用者主动new出来的。

但在Spring框架中创建对象的工作不在由调用者来完成,而是交给IOC容器来创建,再推送给调用者,整个流程完成反转,因此是控制反转

核心思想

把对象的管理权限交给容器,应用程序如果需要使用某个对象的实例那么直接从IOC容器里获取就可以了

好处在于降低了对象与对象之间的耦合性,使得程序的整个体系结构变得更加灵活

在这里插入图片描述
在这里插入图片描述

底层原理

工厂模式加反射机制

  • 工厂模式:通过工厂模式实现对象的创建和管理

  • 反射机制:通过反射机制实现对象的动态创建和初始化

    • 反射与new的区别
      1. 反射和new都是创建对象实例的,但是new对象无法调用该类里面私有private的属性,而反射可以调用类中private的属性!
      2. new属于静态编译。就是在编译的时候把所有的模块都确定,如果有添加或删除某些功能,需要重新编译。但系统不可能一次就把把它设计得很完美,当发现需要更新某些功能时,采用静态编译的话,需要把整个程序重新编译一次才可以实现功能的更新。也就是说,用户需要把以前的软件卸载了,再重新安装才会重新编译!这样的系统耦合严重,难以扩展!
      3. 反射属于动态编译。在运行时确定类型并创建对象,通过反射指定模板,动态的向模板中传入要实例化的对象。动态编译最大限度发挥了Java的灵活性,体现了多态的应用,有以降低类之间的藕合性。其中spring中ioc的核心就是利用了反射解耦合。
  • 通过工厂加new创建对象

public interface Product {
    void printInfo();
}

public class ProductA implements Product {
    @Override
    public void printInfo() {
        System.out.println("This is Product A");
    }
}

public class ProductB implements Product {
    @Override
    public void printInfo() {
        System.out.println("This is Product B");
    }
}

public class ProductFactory {
    public static Product createProduct(String type) {
        if (type.equals("A")) {
            return new ProductA();
        } else if (type.equals("B")) {
            return new ProductB();
        } else {
            throw new IllegalArgumentException("Invalid product type");
        }
    }
}

public class Main {
    public static void main(String[] args) {
        String productType = "A";
        
        // 使用工厂类创建产品对象
        Product product = ProductFactory.createProduct(productType);
        
        // 调用产品对象的方法
        product.printInfo();
    }
}
  • 通过工厂加反射来创建对象
public interface Product {
    void printInfo();
}

public class ProductA implements Product {
    @Override
    public void printInfo() {
        System.out.println("This is Product A");
    }
}

public class ProductB implements Product {
    @Override
    public void printInfo() {
        System.out.println("This is Product B");
    }
}

public class ProductFactory {
    public static Product createProduct(String className) {
        try {
            Class<?> clazz = Class.forName(className);
            Object object = clazz.newInstance();
            if (object instanceof Product) {
                return (Product) object;
            } else {
                throw new IllegalArgumentException("Invalid product type");
            }
        } catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {
            e.printStackTrace();
            throw new IllegalArgumentException("Invalid product type", e);
        }
    }
}

public class Main {
    public static void main(String[] args) {
        String productClassName = "com.example.ProductA";
        
        // 使用工厂类和反射机制创建产品对象
        Product product = ProductFactory.createProduct(productClassName);
        
        // 调用产品对象的方法
        product.printInfo();
    }
}

Bean

声明Bean的方式

  • 在xml配置文件里面通过的标签,
  • 或者通过@Service,@Repository,@Controller等注解
  • @Configuration配置类里通过@Bean注解去声明

spring在启动的时候会去解析这些bean然后保存的IOC容器里面

在这里插入图片描述

实例化Bean的方式

  • 无参构造方法实例化(默认

  • 工厂静态方法实例化

    (1)创建手机工厂类PhoneFactory,创建静态方法获取手机对象getInstance,代码如下:

    public class PhoneFactory {
        //静态方法创建手机
        public static Phone getInstance(){
            System.out.println("手机工厂调用静态方法直接创建···");
            return new HuaWeiPhone();
        }
    }
    

    (2)在applicationContext.xml中创建bean,标签中class属性为手机工厂类,添加factory-method属性,并设置属性值为手机工厂类中的静态方法getInstance。

    在这里插入图片描述

  • 工厂动态方法实例化

    (1)手机工厂类PhoneFactory,创建通过动态方法获取手机对象getPhone,代码如下:

    public class PhoneFactory {
    	//动态方法创建手机
        public Phone getPhone(){
            System.out.println("手机工厂对象调用动态方法创建···");
            return new HuaWeiPhone();
        }
    }
    

    (2)修改applicationContext.xml中配置PhoneFactory的bean标签,再创建Phone的bean标签,指定工厂方法实例和动态工厂方法。

    在这里插入图片描述

Bean的依赖注入方式

  • 构造方法注入
  • set方法注入(命名空间注入本质也是set注入)

Bean依赖注入的数据类型

  • 普通数据类型
  • 引用数据类型
  • 集合数据类型

工作流程

两个阶段

  1. IOC容器的初始化阶段,主要根据程序里面定义的xml文件或者注解等Bean的声明方式,通过解析和加载后生成BeanDeginition,然后把BeanDefinition注册到IOC容器里面,通过注解或者XML声明的Bean都会解析得到一个BeanDefinition实体,这个实体里面会包含bean的一些定义和基本的一些属性,最后把这个BeanDefinition保存到一个Map集合里面从而去完成IOC的一个初始化,IOC容器的作用就是对这些注册的Bean的定义信息进行处理和维护,它是IOC容器控制反转的一个核心

    在这里插入图片描述

  2. 完成Bean的初始化和依赖注入

    1. 通过反射去针对没有设置lazy-init属性的单例Bean进行初始化
    2. 完成Bean的依赖注入

Bean的使用

  • 通常通过@Autowired这样一个注解或者通过BeanFactory.getBean(),从IOC容器里取获取一个指定Bean的一个实例,另外针对设置了lazy-init属性以及非单例bean的一个实例化是在每一次获取Bean对象的时候,调用Bean的初始化方法来完成实例化的,并且springIOC容器不会去管理这些Bean

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值