Spring5参考指南:依赖注入(一)

简介: Spring5参考指南:依赖注入(一)

文章目录



依赖注入


依赖注入就是在Spring创建Bean的时候,去实例化该Bean构造函数所需的参数,或者通过Setter方法去设置该Bean的属性。


Spring的依赖注入有两种基于构造函数的依赖注入和基于setter的依赖注入。


基于构造函数的依赖注入


构造函数的注入是通过构造函数的参数来实现的。如下所示:


public class ExampleBean {
    // Number of years to calculate the Ultimate Answer
    private int years;
    // The Answer to Life, the Universe, and Everything
    private String ultimateAnswer;
    public ExampleBean(int years, String ultimateAnswer) {
        this.years = years;
        this.ultimateAnswer = ultimateAnswer;
    }
}


该Bean有一个两个参数的构造函数,那么怎么注入这些参数呢?


有三种方法。


方法1:按构造函数的类型匹配:


<bean id="exampleBeanA" class="com.flydean.beans.ExampleBean">
        <constructor-arg type="int" value="7500000"/>
        <constructor-arg type="java.lang.String" value="42"/>
    </bean>


这里通过指定参数的类型,即可以指定哪个参数是years,哪个参数是ultimateAnswer。

方法2:构造函数索引:


<bean id="exampleBeanB" class="com.flydean.beans.ExampleBean">
        <constructor-arg index="0" value="7500000"/>
        <constructor-arg index="1" value="42"/>
    </bean>


Spring中可以通过构造函数的索引来指定特定的参数。要注意Spring的索引是从0开始的。


方法3:构造函数名字匹配:


<bean id="exampleBeanC" class="com.flydean.beans.ExampleBeanWithConstructorProperties">
        <constructor-arg name="years" value="7500000"/>
        <constructor-arg name="ultimateAnswer" value="42"/>
    </bean>


如果通过构造函数的名字来匹配,需要注意必须在编译的时候开启调试标志,要不然Spring不能在构造函数中找到参数名。


如果不想启用调试标志,则必须使用@ConstructorProperties JDK注解显式命名构造函数参数。


public class ExampleBeanWithConstructorProperties {
    // Number of years to calculate the Ultimate Answer
    private int years;
    // The Answer to Life, the Universe, and Everything
    private String ultimateAnswer;
    @ConstructorProperties({"years", "ultimateAnswer"})
    public ExampleBeanWithConstructorProperties(int years, String ultimateAnswer) {
        this.years = years;
        this.ultimateAnswer = ultimateAnswer;
    }
}


基于Setter的注入


Setter注入主要用来无参构造器或者获得对象实例之后才设置对象的属性。下面是Setter的例子:


public class SimpleMovieLister {
    // the SimpleMovieLister has a dependency on the MovieFinder
    private MovieFinder movieFinder;
    // a setter method so that the Spring container can inject a MovieFinder
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }
    // business logic that actually uses the injected MovieFinder is omitted...
}


对于的XML文件如下:


<!--Setter DI -->
    <bean id="movieFinder" class="com.flydean.beans.MovieFinder"/>
    <bean id="simpleMovieLister" class="com.flydean.beans.SimpleMovieLister">
        <property name="movieFinder" ref="movieFinder"/>
    </bean>


除了XML配置,也可以使用注解:@Component、@Controller。或者使用@Configuration注解中的@Bean方法。


如何选择?


既然有这样两种注入方式,我们怎么选择呢?


通常来说,对于必须的属性,我们通过构造函数来注入。对于可选属性,我们通过Setter注入。当然你也可以在Setter方法中使用@Required注解。


当然如果第三方类不公开任何setter方法,那么构造函数注入可能是DI的唯一可用形式。


循环依赖


循环依赖主要出现在构造函数注入的情况。


类A通过构造函数注入需要类B的实例,类B通过构造函数注入需要类A的实例。如果为要相互注入的类A和类B配置bean,那么SpringIOC容器在运行时检测到这个循环引用,会抛出BeanCurrentlyInCreationException。


解决方式就是使用Setter注入。


依赖注入的配置详解


基本类型,字符串或者其他


如果< property/>元素的value属性是基本类型,Spring会将其转换为类需要的类型,配置如下:


<!--Setter DI -->
    <bean id="movieFinder" class="com.flydean.beans.MovieFinder">
        <property name="name" value="movie"/>
        <property name="number" value="123456"/>
    </bean>


这是一个常见的Setter注入。为了简洁,也可以使用p-namespace,如下:


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="movieFinder" class="com.flydean.beans.MovieFinder"
          p:name="movie"
          p:number="123456"/>
</beans>


Spring容器使用JavaBeans属性编辑器机制将< value/>元素中的文本转换为java.util.properties实例。这是一个很好的快捷方式,如下所示:


<bean id="mappings"
          class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <!-- typed as a java.util.Properties -->
        <property name="properties">
            <value>
                jdbc.driver.className=com.mysql.jdbc.Driver
                jdbc.url=jdbc:mysql://localhost:3306/mydb
            </value>
        </property>
    </bean>


注意上面例子中的value里面的值。


ref


通过< ref/>标记的bean属性允许在同一容器或父容器中创建对任何bean的引用,而不管它是否在同一XML文件中。bean属性的值可以与目标bean的id属性相同,也可以与目标bean的name属性中的一个值相同。以下示例显示如何使用ref元素:


<ref bean="someBean"/>


内部bean


在< property/> 或者 < constructor-arg/>元素内部的< bean/>元素可以定义一个内部bean,下面是个例子:


<bean id="simpleMovieLister" class="com.flydean.beans.SimpleMovieLister">
        <property name="movieFinder">
            <bean class="com.flydean.beans.MovieFinder">
                <property name="name" value="movie"/>
                <property name="number" value="123456"/>
            </bean>
        </property>
    </bean>


内部bean定义不需要ID或名称。如果指定,容器也不会使用这个值作为标识符。容器在创建时也忽略作用域标志,因为内部bean总是匿名的,并且总是用外部bean创建的。不可能单独访问内部bean,也不可能将它们注入到除封闭bean之外的协作bean中。


集合


< list/>, < set/>, < map/>,和 < props/> 分别被用来设置Java Collection类型List, Set, Map,和 Properties 类型的属性和参数。 下面是个例子:


<bean id="movieFinderE" class="com.flydean.beans.MovieFinder"></bean>
    <bean class="com.flydean.beans.CollectionBean">
        <property name="properties">
            <props>
                <prop key="administrator">administrator@example.org</prop>
                <prop key="support">support@example.org</prop>
                <prop key="development">development@example.org</prop>
            </props>
        </property>
        <property name="arrayList">
            <list>
                <value>"a list element followed by a reference"</value>
            </list>
        </property>
        <property name="hashMap">
            <map>
                <entry key="an entry" value="just some string"/>
                <entry key ="a ref" value-ref="movieFinderE"/>
            </map>
        </property>
        <property name="hashSet">
            <set>
                <value>just some string</value>
                <ref bean="movieFinderE" />
            </set>
        </property>
    </bean>


强类型集合


通过在Java 5中引入泛型类型,可以使用强类型集合。也就是说,可以声明集合类型,使其只能包含(例如)字符串元素。如果使用Spring将强类型集合注入bean,则可以利用Spring的类型转换支持,以便在将强类型集合实例的元素添加到集合之前将其转换为适当的类型。下面的Java类和bean定义的例子:


public class SomeClass {
    private Map<String, Float> accounts;
    public void setAccounts(Map<String, Float> accounts) {
        this.accounts = accounts;
    }
}


<bean id="something" class="com.flydean.beans.SomeClass">
            <property name="accounts">
                <map>
                    <entry key="one" value="9.99"/>
                    <entry key="two" value="2.75"/>
                    <entry key="six" value="3.99"/>
                </map>
            </property>
        </bean>
相关文章
|
4月前
|
XML Java 测试技术
Spring Boot中的依赖注入和控制反转
Spring Boot中的依赖注入和控制反转
|
3月前
|
Java Spring 容器
彻底改变你的编程人生!揭秘 Spring 框架依赖注入的神奇魔力,让你的代码瞬间焕然一新!
【8月更文挑战第31天】本文介绍 Spring 框架中的依赖注入(DI),一种降低代码耦合度的设计模式。通过 Spring 的 DI 容器,开发者可专注业务逻辑而非依赖管理。文中详细解释了 DI 的基本概念及其实现方式,如构造器注入、字段注入与 setter 方法注入,并提供示例说明如何在实际项目中应用这些技术。通过 Spring 的 @Configuration 和 @Bean 注解,可轻松定义与管理应用中的组件及其依赖关系,实现更简洁、易维护的代码结构。
51 0
|
3月前
|
设计模式 自然语言处理 Java
简单了解下Spring中的各种Aware接口实现依赖注入
在Spring框架中,Aware接口是一组用于提供特定资源或环境信息的回调接口。这些接口被设计用来允许Bean获取对Spring容器或其他相关资源的引用,并在需要时进行适当的处理。
36 2
|
3月前
|
自然语言处理 Java 开发者
简单了解下Spring中的各种Aware接口实现依赖注入
【8月更文挑战第21天】在Spring框架中,Aware接口系列是一种特殊的机制,它允许Bean在初始化过程中获取到Spring容器或容器中的特定资源,从而实现了更加灵活和强大的依赖注入方式。本文将围绕Spring中的各种Aware接口,详细探讨它们如何帮助开发者在工作和学习中更好地实现依赖注入。
107 0
|
4月前
|
缓存 Java Spring
Spring循环依赖问题之Spring不支持构造器内的强依赖注入如何解决
Spring循环依赖问题之Spring不支持构造器内的强依赖注入如何解决
|
5月前
|
设计模式 Java 测试技术
Spring Boot中的依赖注入详解
Spring Boot中的依赖注入详解
|
5月前
|
Java Spring 容器
spring如何进行依赖注入,通过set方法把Dao注入到serves
spring如何进行依赖注入,通过set方法把Dao注入到serves
|
4月前
|
XML Java 数据格式
深入理解Spring中的依赖注入原理
深入理解Spring中的依赖注入原理
|
4月前
|
Java Spring 容器
深入理解Spring Boot中的容器与依赖注入
深入理解Spring Boot中的容器与依赖注入
|
5月前
|
XML Java 数据格式
使用 Spring 实现控制反转和依赖注入
自动装配允许Spring容器通过检查已定义的bean来自动解决协作bean之间的依赖关系。 使用XML配置有四种自动装配bean的模式: • no:默认值 - 这意味着不使用自动装配,我们必须显式地命名依赖项。 • byName:按属性名称进行自动装配,因此Spring将查找与需要设置的属性同名的bean。 • byType:类似于按名称进行自动装配,仅基于属性的类型。这意味着Spring将查找具有相同类型的属性来设置的bean。如果有多个bean具有该类型,则框架会抛出异常。 • constructor:基于构造函数参数进行自动装配,意味着Spring将查找具有与构造函数参数相同类型的bea