Loading

IOC容器中的依赖注入(一)

基于Spring官网总结

IOC文档:https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans

一、配置元数据

org.springframework.context.ApplicationContext接口代表Spring IoC容器,并负责实例化,配置和组装Bean。

<?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="..." class="...">  
        <!-- 此bean的协作者和配置在这里 -->
    </bean>
	<!--	该id属性是标识单个bean定义的字符串。
			该class属性定义Bean的类型,并使用完全限定的类名-->
</beans>

有关在Spring容器中使用其他形式的元数据的信息,请参见:

  • 基于注释的配置:Spring 2.5引入了对基于注释的配置元数据的支持。
  • 基于Java的配置:从Spring 3.0开始,Spring JavaConfig项目提供的许多功能成为核心Spring Framework的一部分。因此,您可以使用Java而不是XML文件来定义应用程序类外部的bean。要使用这些新功能,请参阅 @Configuration@Bean@Import,和@DependsOn注释。

Spring配置由容器必须管理的至少一个(通常是一个以上)bean定义组成。基于XML的配置元数据将这些bean配置为<bean/>顶级元素内的<beans/>元素。Java配置通常@Bean@Configuration类中使用带注释的方法


二、实例化容器

容器其实就相当于"bean.xml"此类文件

ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");

三、组成基于XML的配置元数据

通常,每个单独的XML配置文件都代表体系结构中的逻辑层或模块,这样可以使bean定义跨越多个XML文件可能会很有用。

<beans>
    <import resource="services.xml"/>
    <import resource="resources/messageSource.xml"/>
    <import resource="/resources/themeSource.xml"/>

    <bean id="bean1" class="..."/>
    <bean id="bean2" class="..."/>
</beans>

官方建议:

可以但不建议使用相对的“ ../”路径引用父目录中的文件。这样做会创建对当前应用程序外部文件的依赖关系。特别是,对于运行时解析过程选择“最近的”类路径根目录然后查看其父目录的classpath:URL,不建议使用此引用(例如classpath:../services.xml)。类路径配置的更改可能会导致选择其他错误的目录。您始终可以使用标准资源位置而不是相对路径:例如file:C:/config/services.xmlclasspath:/config/services.xml。但是,请注意,您正在将应用程序的配置耦合到特定的绝对位置。通常最好为这样的绝对位置保留一个间接寻址-例如,通过在运行时针对JVM系统属性解析的“ $ {…}”占位符


四、使用容器

// 创建和配置bean
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");

// 检索配置实例
PetStoreService service = context.getBean("petStore", PetStoreService.class);

// 使用配置实例
List<String> userList = service.getUsernameList();

五、依赖注入

    • 依赖:bean 对象的创建依赖于容器!
    • 注入:bean 对象中的所有属性,由容器来注入!

官方解释:

依赖注入(DI)是一个过程,通过该过程,对象只能通过构造函数参数,工厂方法的参数或在构造或创建对象实例后在对象实例上设置的属性来定义其依赖关系(即,与它们一起工作的其他对象),从工厂方法返回,然后,容器在创建bean时注入那些依赖项。

从根本上讲,此过程是通过使用类的直接构造或服务定位器模式来控制其依赖项的实例化或位置的Bean本身的逆过程

DI存在两个主要变体基于构造函数的依赖注入基于Setter的依赖注入

1.基于构造函数的依赖注入

构造函数参数类型匹配

<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg type="int" value="7500000"/>
    <constructor-arg type="java.lang.String" value="42"/>
</bean>

构造函数参数索引

<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg index="0" value="7500000"/>
    <constructor-arg index="1" value="42"/>
</bean>
<!--注意索引从0开始-->

构造函数参数名称

<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg name="years" value="7500000"/>
    <constructor-arg name="ultimateAnswer" value="42"/>
</bean>

注意:当配置文件开始加载的时候,容器(相当于Bean)中管理的对象就已经开始初始化了。

2.基于Setter的依赖注入

bean注入

<!-- 在父上下文中-->
<bean id="accountService" <!-- bean名称与父bean相同 -->
    class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="target">
        <ref parent="accountService"/> <!-- 注意我们是如何引用父bean的 -->
    </property>
    <!-- 在这里按需要插入其他配置和依赖项 -->
</bean>

普通值注入

<bean id="theTargetBean" class="..." />
<bean id="client" class="...">
    <property name="targetName" value="theTargetBean"/>
</bean>

集合:

<list/><set/><map/>,和<props/>元件设置Java的属性和参数Collection类型ListSetMap,和Properties,分别。以下示例显示了如何使用它们

<bean id="moreComplexObject" class="example.ComplexObject">
    <!-- results in a setAdminEmails(java.util.Properties) call -->
    <property name="adminEmails">
        <props>
            <prop key="administrator">administrator@example.org</prop>
            <prop key="support">support@example.org</prop>
            <prop key="development">development@example.org</prop>
        </props>
    </property>
    <!-- results in a setSomeList(java.util.List) call -->
    <property name="someList">
        <list>
            <value>a list element followed by a reference</value>
            <ref bean="myDataSource" />
        </list>
    </property>
    <!-- results in a setSomeMap(java.util.Map) call -->
    <property name="someMap">
        <map>
            <entry key="an entry" value="just some string"/>
            <entry key ="a ref" value-ref="myDataSource"/>
        </map>
    </property>
    <!-- results in a setSomeSet(java.util.Set) call -->
    <property name="someSet">
        <set>
            <value>just some string</value>
            <ref bean="myDataSource" />
        </set>
    </property>
</bean>

映射键或值的值或设置值也可以是以下任意元素:

bean | ref | idref | list | set | map | props | value | null

关于IOC控制反转

控制:谁来控制对象的创建,传统应用程序的对象是由程序本身控制创建的,使用 Spring 后,对象是由 Spring 来创建的。

反转:程序本身不创建对象,而变成被动的接收对象。

依赖注入:就是利用 set 方法来进行注入的。

IOC 是一种编程思想,由主动的编程变成被动的接收。

可以通过 new ClassPathXmlApplicationContext 去浏览一下底层源码。

到了现在,我们彻底不用在程序中去改动了,要实现不同的操作,只需要在 xml 配置文件中进行修改,所谓的 IOC,一句话搞定:对象由 Spring 来创建,管理,装配


posted @ 2021-04-14 22:49  余月七  阅读(141)  评论(0编辑  收藏  举报