Spring的核心机制——依赖注入

引言

       上一篇文章中,我们接上了如何使用idea创建第一个Spring,在文中,Person和Axe含有依赖关系!那么Spring如何管理它们之间的关系呢!!
在这里插入图片描述

Spring核心功能

  • Spring 容器作为超级大工厂, 负责创建、管理所有的Java 对象,这些Java 对象被称为Bean。
  • Spring 容器管理容器中Bean 之间的依赖关系,Spring使用一种被称为“依赖注入”的方式来管理Bean 之间的依赖关系。

Spring本质

       Spring的本质:通过XML配置来驱动Java代码。Spring用的熟:几乎所有Java代码都放在XML去配置。要求:眼中看到的XML配置,心中想的是执行的Java代码。
       bean元素 :驱动使用new调用构造器。 默认它总是调用无参数的构造器。如果想控制它调用有参数的构造器,就需要在<bean…/>元素里添加
              <constructor-arg…/>子元素,每个该元素代表一个构造器参数。
              <constructor-arg…/>子元素里value属性指定的值优先被当成String类处理。为了明确地指定该值的类型,可以指定type属性。
       property元素: 驱动它调用setter方法。 对象创建出来之后,立即就会被调用。
       constructor-arg元素: 驱动调用有参数的构造器。

依赖注入

IOC与依赖注入

       两者是同一行为的两种表达,只是描述角度不同!IOC是从调用者的角度出发,调用者不用再主动·获取依赖对象,而是由Spring容器自动为其赋值,因此调用者由原来的主动获取依赖对象变成了被动接受。而依赖注入是从Spring容器的角度来看,Spring容器负责将依赖对象赋值给调用者的成员变量。

实现方式’

依赖注入可分为3种:

  • 接口注入。很少使用。
  • 设值注入:就是通过property元素控制调用setter方法,就是所谓的设值注入。
  • 构造注入:就是constructor-arg控制调用有参数的构造器,由构造器来注入被依赖组件。

设值注入

public interface Person {
    
    
    //定义一个使用斧头的方法
    public void useAxe();
}

public interface Axe {
    
    
    //Axe接口中定义一个chop()方法
    public String chop();
}

public class Chinese implements Person {
    
    
    private Axe axe;
    public void setAxe(Axe axe ){
    
    
        this.axe=axe;
    }
    @Override
    public void useAxe(){
    
    
        System.out.println(axe.chop());
    }
}

public class StoneAxe implements Axe{
    
    
    @Override
    public String chop(){
    
    
        return "石斧砍柴好慢";
    }
}

<?xml version="1.0" encoding="GBK"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
    <!-- 配置名为person的Bean,其实现类是org.crazyit.app.service.Person类 -->
    <bean id="chinese" class="Chinese">
        <!-- 控制调用setAxe()方法,将容器中axe Bean作为传入参数 -->
        <property name="axe" ref="stoneAxe"/>
    </bean>
    <!-- 配置名为axe的Bean,其实现类是org.crazyit.app.service.Axe类 -->
    <bean id="stoneAxe" class="StoneAxe"/>
    <!-- 配置名为win的Bean,其实现类是javax.swing.JFrame类 -->
    <bean id="win" class="javax.swing.JFrame"/>
    <!-- 配置名为date的Bean,其实现类是java.util.Date类 -->
    <bean id="date" class="java.util.Date"/>
</beans>

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class BeanTest {
    
    
    public static void main(String[] args)throws Exception
    {
    
    
        // 创建Spring容器
        ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-config.xml");
        // 获取id为person的Bean
        Person p = ctx.getBean("chinese" , Person.class);
        // 调用useAxe()方法
        p.useAxe();
    }
}

在这里插入图片描述

使用Spring IoC 容器的三个基本要点
  • 应用程序的各组件面向接口编程。面向接口编程可以将组件之间的精合关系提升到接口层次,从而有利于项目后期的扩展。
  • 应用程序的各组件不再由程序主动创建,而是由Spring容器来负责产生并初始化。
  • Spring采用配置文件或注解来管理Bean的实现类,依赖关系,Spring 容器则根据配置文件或注解,利用反射来创建实例,并为之注入依赖关系。

构造注入

public class Chinese implements Person {
    
    
    private Axe axe;
    public Chinese(Axe axe){
    
    
        this.axe=axe;
    }
    @Override
    public void useAxe(){
    
    
        System.out.println(axe.chop());
    }
}

<?xml version="1.0" encoding="GBK"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
    <!-- 配置名为person的Bean,其实现类是org.crazyit.app.service.Person类 -->
    <bean id="chinese" class="Chinese">
       <constructor-arg ref="stoneAxe"/>
    </bean>
    <!-- 配置名为axe的Bean,其实现类是org.crazyit.app.service.Axe类 -->
    <bean id="stoneAxe" class="StoneAxe"/>
    <!-- 配置名为win的Bean,其实现类是javax.swing.JFrame类 -->
    <bean id="win" class="javax.swing.JFrame"/>
    <!-- 配置名为date的Bean,其实现类是java.util.Date类 -->
    <bean id="date" class="java.util.Date"/>
</beans>

二者区别

区别在于:创建Person 实例中Axe属性的时机不同一一设值注入是先通过无参数的构造器创建一个Bean 实例,然后调用对应的setter 方法注入依赖关系: 而构造注入则直接调用有参数的构造器,当Bean 实例创建完成后,己经完成了依赖关系的注入。

猜你喜欢

转载自blog.csdn.net/qq_41827511/article/details/105281084