写点什么

不会使用 Spring 的配置文件,赶紧把这个甩给他

  • 2022 年 1 月 20 日
  • 本文字数:7834 字

    阅读完需:约 26 分钟

摘要:文章从 Spring 程序的快速使用、Bean 标签的使用和其属性的具体使用,每个属性都用代码来解释,运行结果和案例也写的都很明白。


本文分享自华为云社区《怎样使用Spring的配置文件?带大家一起玩转Spring配置文件》,作者:我是一棵卷心菜 。

一、Spring 程序快速入门


步骤一:导入 Spring 开发的基本包坐标

创建一个 maven 工程,导入 Spring 需要的依赖,为了方便测试,我还导入了一个 Junit 测试包


<dependencies>        <dependency>            <groupId>org.springframework</groupId>            <artifactId>spring-context</artifactId>            <version>5.3.14</version>        </dependency>        <dependency>            <groupId>junit</groupId>            <artifactId>junit</artifactId>            <version>4.12</version>        </dependency>    </dependencies>
复制代码


步骤二:编写 Dao 接口和实现类

接下里,需要编写一个 Dao 接口和其实现类,用来搭建测试的环境,话多不说,直接上代码


public interface UserDao {    void save();}public class UserDaoImpl implements UserDao {    @Override    public void save() {        System.out.println("保存成功~~");    }}
复制代码


步骤三:创建 Spring 核心配置文件

接口和类写完后,就开始进入正题,在类路径下(resources)创建 Spring 的核心配置文件,我取名为 applicationContext.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"       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"></beans>
复制代码


步骤四:在 Spring 配置文件中配置 UserDaoImpl 类

创建好 xml 配置文件后,我要想调用 save()方法,就需要创建 UserDaoImpl 类的对象,这里采用容器的方式。


<bean id="userdao" class="com.sht.dao.impl.UserDaoImpl"></bean>
复制代码


这里的 id 是自定义的,最好是类名的首字母小写,方便于记忆。class 属性值是要创建类对象的所在包路径,我的这个 UserDaoImpl 类所在的包路径就是 com.sht.dao.impl.UserDaoImpl,这一点都不能写错哦!


步骤五:使用 Spring 的 API 获得 Bean 实例

接下来测试一下:


public class UserDaoDemo {    public static void main(String[] args) {        ApplicationContext applicationContext =                new ClassPathXmlApplicationContext("applicationContext.xml");        UserDao userdao = (UserDao) applicationContext.getBean("userdao");        userdao.save();    }}
复制代码


通过 new ClassPathXmlApplicationContext("applicationContext.xml")获取到容器——applicationContext,然后通过 id 对应的属性值获取到 UserDaoImpl 类的对象,这样我们就不需要用 new 的方式来创建对象了!


以上 java 代码还可以写成另一种方式:


public class UserDaoDemo {    public static void main(String[] args) {        ApplicationContext applicationContext =                new ClassPathXmlApplicationContext("applicationContext.xml");        UserDaoImpl userDao = applicationContext.getBean(UserDaoImpl.class);        userDao.save();    }}
复制代码


其中,当参数的数据类型是字符串时,表示根据 Bean 的 id 从容器中获得 Bean 实例,返回是 Object,需要强转。


当参数的数据类型是 Class 类型时,表示根据类型从容器中匹配 Bean 实例,特别注意的是:当容器中相同类型的 Bean 有多个时,则此方法会报错。


运行结果:



结果正确,到了这里,spring 的配置文件你已经有了基本的了解,接下来让我们看看 spring 配置文件中其它的细节使用吧!

二、Spring 配置文件使用

1、Bean 标签基本配置


基本介绍

用于配置对象交由 Spring 来创建

默认情况下它调用的是类中的无参构造函数,如果没有无参构造函数则不能创建成功,对于有参构造器,后面会慢慢讲到


基本属性

id:Bean 实例在 Spring 容器中的唯一标识

class:Bean 的全限定名称


这两个基本属性在快速入门中已经使用过了,就不最多介绍了


Bean 标签范围配置(Scope)



修改 xml 配置文件,在原来的 bean 中加入 scope="singleton",这就意味着,我们不管创建多少个对象,都是同一个


<bean id="userdao" class="com.sht.dao.impl.UserDaoImpl" scope="singleton"></bean>
复制代码


写一个测试代码


public void test1(){    ApplicationContext context =            new ClassPathXmlApplicationContext("applicationContext.xml");    UserDao userdao1 = (UserDao) context.getBean("userdao");    System.out.println(userdao1);    UserDao userdao2 = (UserDao) context.getBean("userdao");    System.out.println(userdao2);    System.out.println("是否为同一个对象实例:" + (userdao1 == userdao2));}
复制代码


运行结果:



继续修改 xml 配置文件,把 scope="singleton"改为 scope="prototype",即表明,我们用其创建对象时,不是同一个对象实例


上面的测试代码不变,运行结果:



Bean 标签实例化时机

小伙伴们可能就有疑问了,上面这两种方式是什么时候创建对象实例的呢?不要急,咱们慢慢道来。


为了方便效果的展现,我在 UserDaoImpl 类的无参构造器中加入一句代码,用来区别创建实例的时机


 public UserDaoImpl(){        System.out.println("UserDaoImpl开始创建");    }
复制代码


scope 为 singleton 时

运行 debug,点击 F8



我们可以发现,从加载配置文件的时候就开始创建了对象实例



scope 为 prototype 时

运行 debug,按下 F8,发现控制台并没有打印“UserDaoImpl 开始创建”,说明配置文件并没有加载对象实例



再次按 F8 下一步



我们可以发现控制台终于打印了“UserDaoImpl 开始创建”



总结

当 scope 的取值为 singleton 时,当应用加载,创建容器时,对象就被创建了;当 scope 的取值为 prototype 时,当使用对象时,才创建新的对象实例。


Bean 生命周期配置

在 UserDaoImpl 类中添加两个方法


public void init(){        System.out.println("初始化方法");    }  public void destory(){        System.out.println("销毁方法");    }
复制代码


修改 xml 配置文件,init-method:指定类中的初始化方法名称,destroy-method:指定类中销毁方法名称


<bean id="userdao" class="com.sht.dao.impl.UserDaoImpl"          scope="singleton"          init-method="init"          destroy-method="destory"></bean>
复制代码


编写测试代码


public void test3(){        ApplicationContext context =                new ClassPathXmlApplicationContext("applicationContext.xml");        UserDao userdao1 = (UserDao) context.getBean("userdao");        System.out.println(userdao1);        UserDao userdao2 = (UserDao) context.getBean("userdao");        System.out.println(userdao2);        System.out.println("是否为同一个对象实例:" + (userdao1 == userdao2));        //这里用来关闭容器        ((ClassPathXmlApplicationContext) context).close();    }
复制代码


运行结果:



从这个例子,相信大家可以自己推测出创建对象、初始化、方法调用以及销毁的先后顺序了


Bean 实例化三种方式


方式一:无参构造方法实例化(重点)

其实我们前面一直使用的就是这一种方法,但是需要注意的是,这种方法会根据默认无参构造方法来创建类对象,如果 bean 中没有默认无参构造函数,将会创建失败


方式二:工厂静态方法实例化(了解)

创建一个静态工厂类,直接返回 UserDaoImpl 类的对象实例


public class StaticFactory {    public static UserDao getUserDao(){        return new UserDaoImpl();    }}
复制代码


编写 xml 配置文件的 bean,这里的 class 属性值是静态工厂类对应的包的路径,factory-method 对应的属性值是类中的方法名


<bean id="userdao" class="com.sht.factory.StaticFactory" factory-method="getUserDao"></bean>
复制代码


编写代码测试


public class UserDaoDemo {    public static void main(String[] args) {        ApplicationContext applicationContext =                new ClassPathXmlApplicationContext("applicationContext.xml");        UserDao userdao = (UserDao) applicationContext.getBean("userdao");        userdao.save();    }}
复制代码


最终的运行结果还会是:“保存成功~~”


方式三:工厂实例方法实例化(了解)

创建一个工厂类,同样返回 UserDaoImpl 类的对象实例


public class DynamicFactory {    public UserDao getUserDao(){        return new UserDaoImpl();    }}
复制代码


编写 xml 配置文件的 bean,这里的 class 属性值是工厂类对应的包的路径,第一个 bean 可以得到工厂类的对象,再写一个 bean,用来获取 UserDaoImpl 类的对象实例。factory-bean 属性值代表从哪个工厂里面拿,factory-method 对应的属性值是类中的方法名


<bean id="factory" class="com.sht.factory.DynamicFactory"></bean><bean id="userdao" factory-bean="factory" factory-method="getUserDao"></bean>
复制代码


最终的运行结果也是:“保存成功~~”


总结



2、Bean 的依赖注入


基本介绍

依赖注入(Dependency Injection):它是 Spring 框架核心 IOC 的具体实现。


在编写程序时,通过控制反转,把对象的创建交给了 Spring,但是代码中不可能出现没有依赖的情况。IOC 解耦只是降低他们的依赖关系,但不会消除。例如:业务层仍会调用持久层的方法。


那这种业务层和持久层的依赖关系,在使用 Spring 之后,就让 Spring 来维护了。简单的说,就是坐等框架把持久层对象传入业务层,而不用我们自己去获取。


Bean 的依赖注入方式

方式一:有参构造方法

前面讲的都是无参构造方法,现在讲讲有参构造方法。我们先创建一个 UserService 接口和其实现类 UserServiceImpl


public interface UserService {    void save();}public class UserServiceImpl implements UserService {    private UserDao userdao;    public UserServiceImpl(UserDao userdao) {        this.userdao = userdao;    }    @Override    public void save() {        userdao.save();    }}
复制代码


编写 xml 配置文件的 bean,class 属性值分别对应类下的包路径。<constructor-arg name="userdao" ref="userdao"></constructor-arg>中 name 属性值是相应 set 方法名的去掉 set 后的首字母小写,ref 是引入引入数据类型,即表示着对象属性的注入


<bean id="userdao" class="com.sht.dao.impl.UserDaoImpl"></bean>  <bean id="userService"  class="com.sht.service.impl.UserServiceImpl">        <constructor-arg name="userdao" ref="userdao"></constructor-arg>  </bean>
复制代码


方式二:set 方法

接口不变,改变一下 UserServiceImpl 类,需要注意的是,setUserdao()的权限是 public,不能写成 private 哦


public class UserServiceImpl implements UserService {    private UserDao userdao;    //权限是public    public void setUserdao(UserDao userdao){        this.userdao = userdao;    }    @Override    public void save() {        userdao.save();    }}
复制代码


编写 xml 配置文件的 bean,class 属性我就不再说明了。重点讲解的是<property name="userdao" ref="userdao"></property>;name 属性值是相应 set 方法名的去掉 set 后的首字母小写,ref 是引入引入数据类型,即表示着对象属性的注入;这里把 UserDaoImpl 类的对象注入到 UserServiceImpl 类中,就可以调用其 save()方法了


<bean id="userdao" class="com.sht.dao.impl.UserDaoImpl"></bean>  <bean id="userService"  class="com.sht.service.impl.UserServiceImpl">        <property name="userdao" ref="userdao"></property>  </bean>
复制代码


测试代码:


public void test5(){        ApplicationContext context =                new ClassPathXmlApplicationContext("applicationContext.xml");        UserService userService = (UserService) context.getBean("userService");        userService.save();    }
复制代码


运行结果:



此外,set 方法中有一个特殊的方法:P 命名空间注入。其本质也是 set 方法注入,但比起上述的 set 方法注入更加方便,主要体现在配置文件中,如下:


引入 xmlns:p="http://www.springframework.org/schema/p"名称空间,其次 p:userdao-ref 属性值是跟 ref 对应的属性值的含义是一样的,这种方法可以作为了解


<?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="userdao" class="com.sht.dao.impl.UserDaoImpl"></bean>      <bean id="userService" class="com.sht.service.impl.UserServiceImpl" p:userdao-ref="userdao"></bean></beans>
复制代码

3、Bean 的依赖注入数据类型


普通数据类型的注入

我用 set 方法的方式,讲解 bean 的依赖注入。继续在 UserDaoImpl 类中添加两个基本数据类型和它们的 set 方法


private String name;private Integer age;public void setName(String name) {    this.name = name;}public void setAge(Integer age) {    this.age = age;}public void show() {    System.out.println("名字是" + name + "的年龄是" + age);}
复制代码


修改 xml 配置文件的 bean,name 的属性值代表着 set 方法的名,value 的属性值表示你想要填入的属性值


<bean id="userDao" class="com.sht.dao.impl.UserDaoImpl">        <property name="name" value="卷心菜"></property>        <property name="age" value="20"></property></bean>
复制代码


写一个测试类:


public void test7(){        ApplicationContext context =                new ClassPathXmlApplicationContext("applicationContext.xml");        UserDaoImpl contextBean = context.getBean(UserDaoImpl.class);        contextBean.show();    }
复制代码


运行结果:



集合数据类型的注入

List<String>类型的注入

继续在 UserDaoImpl 类中改动代码:


private List<String> stringList;public void setStringList(List<String> stringList) {    this.stringList = stringList;}public void showStringList() {    System.out.println(stringList);}
复制代码


修改 xml 配置文件,注入基本数据类型就是两个关键字<list>和<value>


<bean id="userDao" class="com.sht.dao.impl.UserDaoImpl">       <property name="stringList">          <list>              <value>111</value>              <value>222</value>              <value>333</value>          </list>       </property>  </bean>
复制代码


运行结果:



List<User>类型的注入

先创建一个 User 类,有对应的 get 和 set 方法,还有 toString 方法,方便测试使用


public class User {    private Integer id;    private String username;    private String password;    public Integer getId() {        return id;    }    public void setId(Integer id) {        this.id = id;    }    public String getUsername() {        return username;    }    public void setUsername(String username) {        this.username = username;    }    public String getPassword() {        return password;    }    public void setPassword(String password) {        this.password = password;    }    @Override    public String toString() {        return "User{" +                "id=" + id +                ", username='" + username + '\'' +                ", password='" + password + '\'' +                '}';    }}
复制代码


修改 xml 配置文件的 bean,可以看出,与之前不同的是,<list>中用的是<ref>标签,这个标签表示的是注入引用数据类型


<bean id="user01" class="com.sht.domain.User">        <property name="id" value="1"></property>        <property name="username" value="卷心菜"></property>        <property name="password" value="123456"></property> </bean>     <bean id="user02" class="com.sht.domain.User"></bean>        <bean id="userDao" class="com.sht.dao.impl.UserDaoImpl">       <property name="userList">           <list>               <ref bean="user01"></ref>               <ref bean="user02"></ref>           </list>       </property>    </bean>
复制代码


运行结果:



Map<String,User> 类型的注入继续在 UserDaoImpl 类中改动代码:


private Map<String, User> stringUserMap;public void setStringUserMap(Map<String, User> stringUserMap) {    this.stringUserMap = stringUserMap;}public void showStringUserMap() {    System.out.println(stringUserMap);}
复制代码


修改 xml 配置文件,与之前不同的是,当使用的是 map 时,标签用的是<map>和标签<entry>,使用方法跟 list 标签差不多


<bean id="user01" class="com.sht.domain.User">    <property name="id" value="1"></property>    <property name="username" value="卷心菜"></property>    <property name="password" value="123456"></property></bean>
<bean id="userDao" class="com.sht.dao.impl.UserDaoImpl"> <property name="stringUserMap"> <map> <entry key="key1" value-ref="user01"></entry> </map> </property></bean>
复制代码


运行结果:



需要注意的是,我们在选择 key 属性时,会有一个如图所示的 key-ref 的提示,这代表着我们要用的 key 是一个引入数据类型,因为我用的 key 是 String,所以选择 key



当使用 value-ref 时,也会出现 value 的值,其用法跟上面一样



Properties 类型的注入继续在 UserDaoImpl 类中改动代码:


private Properties properties;public void setProperties(Properties properties) {    this.properties = properties;}public void showProperties(){    System.out.println(properties);}
复制代码


修改 xml 配置文件,与之前的不同之处就是标签使用的是<props>和标签<prop>,使用的方法也是跟上面的方法类似


<bean id="userDao" class="com.sht.dao.impl.UserDaoImpl">       <property name="properties">           <props>               <prop key="key01">value1</prop>               <prop key="key02">value2</prop>           </props>       </property> </bean>
复制代码


运行结果:


4、引入其他配置文件(分模块开发)


创建一个新的配置文件 applicationContext1.xml,实际开发中,Spring 的配置内容非常多,这就导致 Spring 配置很繁杂且体积很大,所以,可以将部分配置拆解到其他配置文件中,而在 Spring 主配置文件通过 import 标签进行加载


把 applicationContext1.xml 配置文件中的配置内容引入到 applicationContext.xml 的实现方式:


<import resource="applicationContext1.xml"></import>
复制代码

总结


以上就是 Spring 配置文件的相关知识点,带大家来看看 Spring 的重点配置:



点击关注,第一时间了解华为云新鲜技术~

发布于: 刚刚阅读数: 2
用户头像

提供全面深入的云计算技术干货 2020.07.14 加入

华为云开发者社区,提供全面深入的云计算前景分析、丰富的技术干货、程序样例,分享华为云前沿资讯动态,方便开发者快速成长与发展,欢迎提问、互动,多方位了解云计算! 传送门:https://bbs.huaweicloud.com/

评论

发布
暂无评论
不会使用Spring的配置文件,赶紧把这个甩给他