Spring-IoC实现依赖注入的三种方式
本文最后更新于 1127 天前,其中的信息可能已经有所发展或是发生改变。

Spring Framework

前言

在spring中最重要的两个概念,莫过于IoC((Inversion of Control,控制反转)和AOP(Aspect Oriented Programming,面向切面编程)。

而在spring中IoC作为一个容器,通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。

值得区分的是IoC为一种思想,DI(Dependency Injection,依赖注入)为实现方式。

所以控制反转就是依赖对象的方式反转,即对象的创建,获取,销毁等,交由IoC容器管理。

以下为实现DI的三种方式。

ioc

实现DI

环境准备

依赖导入

直接导入spring-mvc的依赖,其中包括core,cop,context等。

依赖

<dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.9</version>
</dependency>

测试类

public class Dog {
    private String name;

    public Dog() {
        System.out.println("Dog的无参构造被调用!");
    }

    public Dog(String name) {
        this.name = name;
        System.out.println("Dog的有参构造被调用!");
    }

    public void printStr(){
        System.out.println("狗的名字是;"+ this.name);
    }
    public String print(){
        return "狗的名字是;"+ this.name;
    }

    .......
public class User {

    private String name;
    private Dog dog;
    private String[] movies;
    private List<String> hobbies;
    private Map<String,String> tel;
    private Set<String> games;
    private Properties info;
    private String refer;

    .....

    public void printStr(){
        System.out.println("名字:"+ name);
        System.out.println("狗:"+ dog.print());
        System.out.print("电影:");
        for (String movie:movies){
            System.out.print("<<"+movie+">>\t");
        }
        System.out.println();
        System.out.println("爱好:"+hobbies);
        System.out.println("电话:"+tel);
        System.out.println("游戏:"+games);
        System.out.println("配置:"+info);
        System.out.println("引用:"+refer);
    }

配置文件

<?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 http://www.springframework.org/schema/beans/spring-beans.xsd">

    .............

</beans>

构造器注入

无参注入

 <!--无参构造-->
    <bean id="dog" class="space.xycd.entity.Dog">
        <property name="name" value="旺财"/>
    </bean>

有参注入

下标-index
<!--通过下标index-->
    <bean id="dog1" class="space.xycd.entity.Dog">
        <constructor-arg index="0" value="旺财-index"/>
    </bean>
名字-name
<!--通过参数名name-->
    <bean id="dog2" class="space.xycd.entity.Dog">
        <!-- name指参数名 -->
        <constructor-arg name="name" value="旺财-name"/>
    </bean>
类型-type
<!--通过参数类型type -->
    <bean id="dog3" class="space.xycd.entity.Dog">
        <constructor-arg type="java.lang.String" value="旺财-type"/>
    </bean>

Set注入

常量

<!--常量-->
    <bean id="user1" class="space.xycd.entity.User">
        <property name="name" value="XY"/>
    </bean>

数组

<!--数组-->
    <bean id="user3" class="space.xycd.entity.User">
        <property name="movies">
            <array>
                <value>星际迷航</value>
                <value>异形</value>
                <value>普罗米修斯</value>
            </array>
        </property>
    </bean>

引用

<!--Bean-->
    <bean id="user2" class="space.xycd.entity.User">
        <property name="dog" ref="dog"/>
    </bean>

Set

 <!--Set-->
    <bean id="user6" class="space.xycd.entity.User">
        <property name="games">
            <set>
                <value>LOL</value>
                <value>BOB</value>
                <value>COC</value>
            </set>
        </property>
    </bean>

List

 <!--List-->
    <bean id="user4" class="space.xycd.entity.User">
        <property name="hobbies">
            <list>
                <value>听歌</value>
                <value>看电影</value>
                <value>打游戏</value>
            </list>
        </property>
    </bean>

Map

 <!--Map-->
    <bean id="user5" class="space.xycd.entity.User">
        <property name="tel">
            <map>
                <entry key="警察" value="110"/>
                <entry key="火警" value="119"/>
            </map>
        </property>
    </bean>

Properties

<!--Properties-->
    <bean id="user7" class="space.xycd.entity.User">
        <property name="info">
            <props>
                <prop key="学号">222222</prop>
                <prop key="性别">男</prop>
                <prop key="姓名">小明</prop>
            </props>
        </property>
    </bean>

Null

<!--Null-->
    <bean id="user8" class="space.xycd.entity.User">
        <property name="refer"><null/></property>
    </bean>

命名空间注入

p标签

约束文件

xmlns:p="http://www.springframework.org/schema/p"
<!--p命名空间注入-->
    <bean id="dogp" class="space.xycd.entity.Dog" p:name="旺财-p"/>

c标签

约束文件

xmlns:c="http://www.springframework.org/schema/c"
 <!--c命名空间注入-->
    <bean id="dogc" class="space.xycd.entity.Dog" c:name="旺财-c"/>

测试结果

测试结果

分析总结

值得注意的几点:

  • 有参构造注入由有参构造方法完成。
  • set注入由无参构造+setter方法共同完成。
  • c命名空间注入,也是通过有参构造注入完成,结果也反映出。
  • p命名空间注入,通过无参+setter方法注入完成,结果也反映出。
  • 可以观察到,在获取bean对象之前,加载xml配置文件时,bean便被实例化,并且由官方文档可知,默认为单例模式。

此外,官方推荐有参构造注入的方式,平常貌似set注入用的更多,当然也可以采用混合的方式。以下为官方原文。

Constructor-based or setter-based DI?

Since you can mix constructor-based and setter-based DI, it is a good rule of thumb to use constructors for mandatory dependencies and setter methods or configuration methods for optional dependencies. Note that use of the @Required annotation on a setter method can be used to make the property be a required dependency; however, constructor injection with programmatic validation of arguments is preferable.

The Spring team generally advocates constructor injection, as it lets you implement application components as immutable objects and ensures that required dependencies are not null. Furthermore, constructor-injected components are always returned to the client (calling) code in a fully initialized state. As a side note, a large number of constructor arguments is a bad code smell, implying that the class likely has too many responsibilities and should be refactored to better address proper separation of concerns.

Setter injection should primarily only be used for optional dependencies that can be assigned reasonable default values within the class. Otherwise, not-null checks must be performed everywhere the code uses the dependency. One benefit of setter injection is that setter methods make objects of that class amenable to reconfiguration or re-injection later. Management through JMX MBeans is therefore a compelling use case for setter injection.

Use the DI style that makes the most sense for a particular class. Sometimes, when dealing with third-party classes for which you do not have the source, the choice is made for you. For example, if a third-party class does not expose any setter methods, then constructor injection may be the only available form of DI.

参考文献

--Spring 5.3.9

文章作者:XY
文章链接:https://notoop.com/archives/spring-ioc-implement-dependency-injection/
版权声明:本文版权归作者所有,欢迎转载,但转载请注明来自本博客X to Y‘Blog
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇
error: Content is protected !!