SpringIOC手动(装配)注入:set方法注入

  • Post author:
  • Post category:其他


1、我的上一篇博文




介绍SpringIOC的三种Bean对象实例化方法_你是我的日月星河的博客-CSDN博客


icon-default.png?t=M4AD
https://blog.csdn.net/weixin_46281472/article/details/124871658


2、本篇博客的背景和目的

目前我本人正在学习SpringFramework的知识,这也是这个专栏的主题。我前面的几篇博文中,简单的认识了一下SpringFramework,记录了SpringFramework的环境搭建,记录了SpringIOC如何加载配置文件,记录了SpringIOC三种Bean对象的实例化方法。本篇博客我记录一下SpringIOC手动注入的方法。其实目前大部分都使用的是自动注入的方法,手动注入使用的不多。

3、什么是注入呢?

首先看一张图吧:

在上面的这张图中,我们在UserService类中使用UserDao对象,这就是注入。可以称为:将UserDao注入到UserService中。

无论是手动设置注入,还是后面我会记录到的自动注入,都是要让Spring帮助我们完成类似于上面的工作。

4、手动注入的四种方式

set方法注入,构造器注入,静态工厂注入,实例化工厂注入。

(这是不是跟SpringIOC实例化Bean对象的三种方式有点类似呢?其实是真的很类似)

5、set方法手动注入的逻辑思路

既然使用的是set方法注入,那么就一定会使用到set方法。其次,我们还需要使用到XML配置文件,我们要告诉Spring,具体的对应关系是什么。

下面看两张图片吧,也是例子:


其实逻辑也并不难理解,就是在实体类中写了属性的set方法以后,还需要在XML文件中进行一下配置。然后我们就可以使用getBean()方法,获得已经实例化好的对象。

6、我的POM文件

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.dcy</groupId>
  <artifactId>spring04</artifactId>
  <version>1.0-SNAPSHOT</version>

  <name>spring04</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
  </properties>

  <dependencies>

<!--    这个是Spring框架的核心依赖-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.2.12.RELEASE</version>
    </dependency>

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>

  </dependencies>

  <build>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-jar-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
        <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
        <plugin>
          <artifactId>maven-site-plugin</artifactId>
          <version>3.7.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-project-info-reports-plugin</artifactId>
          <version>3.0.0</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>

上面是我的POM文件,我使用的JDK版本是11的,已经算是比较高的了(17,18这些版本太高了,很多不兼容,不建议使用)。我创建项目的时候使用了一个初始化模板,所以有了下面的插件,其实这些插件不重要,建议读者创建空的Maven项目就可以了。最重要的是两个依赖。其实junit依赖也可以不要,因为这个是测试的依赖,我并没有在测试文件夹中编写代码。

7、我的两个实体类代码

这里我就不展示我的文件结构了,读者随便创建个Maven文件就可以,包的名称和结构随大家调整命名。

第一个实体类:UserDao,这个类是代dao包下面的,比较简单,我只写了一个共有的方法,代码如下:

package com.dcy.dao;

public class UserDao {

    public void test(){
        System.out.println("UserDao");
    }
}

这里UserDao默认使用的构造方法当然就是空构造方法。

第二个实体类:UserService。这个实体类中有一个参数是UserDao对象,并且UserDao对象我写了set方法(

这个是使用set方法注入所必须的,要不然XML文件是会报错的,这也是IDEA这个开发工具的优点

)。代码如下:

package com.dcy.service;

import com.dcy.dao.UserDao;

//import javax.annotation.Resource;

public class UserService {

//    @Resource
    private UserDao userDao;
    public void setUserDao(UserDao userDao){
        this.userDao=userDao;
    }

    public void test(){
        System.out.println("UserService");
        userDao.test();
    }
}

这里我多说一下:我上面的代码,在test()方法里面,调用了userDao的test()方法,并且这个UserService类没有构造方法,也就是说,如果我们不使用SpringFramework框架的话,当我们创建一个UserService对象以后,一定要先调用setUserDao方法初始化对象里面的userDao属性对象,然后才能调用UserService对像的test()方法,否则就会报空指针异常!!

8、我的XML文件代码

XML配置文件的代码如下所示:

<?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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">
    <bean id="UserDao" class="com.dcy.dao.UserDao"></bean>
    <bean id="UserService" class="com.dcy.service.UserService">
        <property name="userDao" ref="UserDao"></property>
    </bean>

</beans>

首先我们先写了一个bean标签,将UserDao交给SpringIOC管理,也就是对UserDao使用构造器实例化方法进行实例化。然后下面又是一个bean标签,这个bean标签是将UserService交给了SpringIOC进行管理,使用的也是默认的构造器实例化方法。至于id属性和class属性,这我就不在解释了,本专栏前面几篇博客都介绍过了。然后在第二个bean标签里面,

还嵌套为了一个property标签,这个是本博客的重点

:因为UserService中还有一个UserDao类型的对象属性,因此在我们创建一个UserService类的对象的时候,我们还需要初始化其中的UserDao对象,否则它就是空指针的。这个初始化的过程SpringIOC可以帮助我们完成,但是我们需要告诉SpringIOC具体的关系是什么,也就是需要配置。因此,就有了bean标签里面的property标签。

property标签的name属性值是类中的一个对象参数属性名

,在我们这个例子中,就是属性名:userDao。

ref属性值是在XML文件中,类的属性参数对象所属类在XML文件中对应的bean标签的id属性值

。这两个属性一起,就容易理解了,

也就是告诉SpringIOC,注入的时候,用哪一个类初始化哪一个属性

9、进行一下测试

我直接在Main方法里面测试了,代码如下:

package com.dcy;

//import com.dcy.service.AccountService;
import com.dcy.service.UserService;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Starter {
    public static void main(String[] args) {
        //首先加载配置文件
        BeanFactory factory=new ClassPathXmlApplicationContext("spring04.xml");
        //仍然是通过getBean()方法获得对应的对象
        UserService userService= (UserService) factory.getBean("UserService");
        userService.test();
    }
}

上面的代码比较简单,就是先加载我们的配置文件,我的配置文件名是:spring04.xml。然后通过getBean()方法获得一个UserService类的对象,最后调用它的test()方法。输出结果如下:

很明显,并没有报空指针异常。是SpringIOC帮助我们在后面做了很多工作。

10、类中属性参数的类型是基本类型怎么办呢?

我们上面简单的示例代码中,使用的是自定义的Bean对象的嵌套,但是,如果类中属性参数的类型是基本类型,我们又该怎么办呢?比如字符串类型,整型(这里统一说的是包装类),甚至是集合呢?

一样的道理,同样还是需要我们写好类中的set()方法。

然后就是修改XML配置文件,说的更具体一点,就是修改property标签。

下面举一个简单的例子,先看我们的实体类代码:

package com.dcy.service;

public class UserService {

//    @Resource
    private String name;
    public void setName(String name){
        this.name=name;
    }

    public void test(){
        System.out.println("UserService的名字是"+name);
    }
}

里面包含一个属性name,类型是String。如果我们不使用SpringFramework的话,不做配置,那么我们需要先设置其中的name属性值,然后再调用test()方法,否则new出来的UserService对象的name属性值就是null。

下面是XML文件的代码:

<?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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">
    <bean id="UserService" class="com.dcy.service.UserService">
        <property name="name" value="口水甜"></property>
    </bean>

</beans>

将property标签里面原先的ref属性换成了 value属性。

value属性的值将作为类中参数的值

;这个是比较容易理解的。

下面看一下在Main方法中测试的代码和结果:

package com.dcy;

//import com.dcy.service.AccountService;
import com.dcy.service.UserService;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Starter {
    public static void main(String[] args) {
        //首先加载配置文件
        BeanFactory factory=new ClassPathXmlApplicationContext("spring04.xml");
        //仍然是通过getBean()方法获得对应的对象
        UserService userService= (UserService) factory.getBean("UserService");
        userService.test();
    }
}

输出结果如下:

口水甜  三个字被打印出来了,并没有打印null。

但是,如果参数是List类型,Map类型,Set类型的怎么办呢?

当然还是修改property标签,这里我就不粘贴代码了,情况比较多,我直接粘贴具体的截图了,如下所示:

上面分别是XML文件修改的情况,其实:这种基本类型,List,Map使用的不多,不太可能所有的对象,这些属性值都一样,那也没有意义。基本使用的都是最上面列举的注入我们自定义实体类的例子。这个基本类型的做一个了解就好了,不常用的话也记不住,用的时候上网查就好了。

11、总结一下吧

这篇博客记录了使用set方法将一个实体类注入到另一个实体类的情况,需要我们写set()方法,然后修改XML配置文件。属于我们手动注入。还是比较麻烦的。

12、我本专栏的下一篇博客



版权声明:本文为weixin_46281472原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。