当前位置:   article > 正文

idea中生成spring的 xml配置文件_Java灵魂框架:Spring(3)——装配 Spring Bean 详解

idea spring.xml

本文转载于博客园我没有三颗心脏的博客.

前面小编相继给大家介绍了SSM框架组合的Spring MVC框架和Mybaits框架,今天开始小编将开始为大家介绍三大框架之Spring框架,本期学习内容主要来源于博客园我没有三颗心脏的博客的个人博客,个人感觉写的很不错,故而转载与大家分享.Spring框架的学习将分为4个部分,小编将分四天陆续的向大家介绍.欢迎大家关注小编,与小编进行交流.

46ec85016af95b01db1f1005556cb95e.png

装配 Bean 的概述

前面已经介绍了 Spring IoC 的理念和设计,这一篇文章将介绍的是如何将自己开发的 Bean 装配到 Spring IoC 容器中。

大部分场景下,我们都会使用 ApplicationContext 的具体实现类,因为对应的 Spring IoC 容器功能相对强大。

而在 Spring 中提供了 3 种方法进行配置:

  • 在 XML 文件中显式配置
  • 在 Java 的接口和类中实现配置
  • 隐式 Bean 的发现机制和自动装配原则

方式选择的原则

在现实的工作中,这 3 种方式都会被用到,并且在学习和工作之中常常混合使用,所以这里给出一些关于这 3 种优先级的建议:

1.最优先:通过隐式 Bean 的发现机制和自动装配的原则。

基于约定由于配置的原则,这种方式应该是最优先的

  • 好处:减少程序开发者的决定权,简单又不失灵活。

2.其次:Java 接口和类中配置实现配置

在没有办法使用自动装配原则的情况下应该优先考虑此类方法

  • 好处:避免 XML 配置的泛滥,也更为容易。
  • 典型场景:一个父类有多个子类,比如学生类有两个子类,一个男学生类和女学生类,通过 IoC 容器初始化一个学生类,容器将无法知道使用哪个子类去初始化,这个时候可以使用 Java 的注解配置去指定。

3.最后:XML 方式配置

在上述方法都无法使用的情况下,那么也只能选择 XML 配置的方式。

  • 好处:简单易懂(当然,特别是对于初学者)
  • 典型场景:当使用第三方类的时候,有些类并不是我们开发的,我们无法修改里面的代码,这个时候就通过 XML 的方式配置使用了。

通过 XML 配置装配 Bean

使用 XML 装配 Bean 需要定义对应的 XML,这里需要引入对应的 XML 模式(XSD)文件,这些文件会定义配置 Spring Bean 的一些元素,当我们在 IDEA 中创建 XML 文件时,会有友好的提示:

0938ff4a85208c4cb1e91399ccd1deea.png

一个简单的 XML 配置文件如下:

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

这就只是一个格式文件,引入了一个 beans 的定义,引入了 xsd 文件,它是一个根元素,这样它所定义的元素将可以定义对应的 Spring Bean

装配简易值

先来一个最简单的装配:

简单解释一下:

  • id 属性是 Spring 能找到当前 Bean 的一个依赖的编号,遵守 XML 语法的 ID 唯一性约束。必须以字母开头,可以使用字母、数字、连字符、下划线、句号、冒号不能以 / 开头
  • 不过 id 属性不是一个必需的属性,name 属性也可以定义 bean 元素的名称,能以逗号或空格隔开起多个别名,并且可以使用很多的特殊字符,比如在 Spring 和 Spring MVC 的整合中,就得使用 name 属性来定义 bean 的名称,并且使用 / 开头。
  • 注意: 从 Spring 3.1 开始,id 属性也可以是 String 类型了,也就是说 id 属性也可以使用 / 开头,而 bean 元素的 id 的唯一性由容器负责检查。
  • 如果 id 和 name 属性都没有声明的话,那么 Spring 将会采用 “全限定名#{number}” 的格式生成编号。 例如这里,如果没有声明 “id="c"” 的话,那么 Spring 为其生成的编号就是 “pojo.Category#0”,当它第二次声明没有 id 属性的 Bean 时,编号就是 “pojo.Category#1”,以此类推。
  • class 属性显然就是一个类的全限定名
  • property 元素是定义类的属性,其中的 name 属性定义的是属性的名称,而 value 是它的值。

这样的定义很简单,但是有时候需要注入一些自定义的类,比如之前饮品店的例子,JuickMaker 需要用户提供原料信息才能完成 juice 的制作:

这里先定义了一个 name 为 source 的 Bean,然后再制造器中通过 ref 属性去引用对应的 Bean,而 source 正是之前定义的 Bean 的 name ,这样就可以相互引用了。

  • 注入对象:使用 ref 属性

装配集合

有些时候我们需要装配一些复杂的东西,比如 Set、Map、List、Array 和 Properties 等,为此我们在 Packge【pojo】下新建一个 ComplexAssembly 类:

package pojo;import java.util.List;import java.util.Map;import java.util.Properties;import java.util.Set;public class ComplexAssembly {  private Long id; private List list; private Map map; private Properties properties; private Set set; private String[] array; /* setter and getter */}

这个 Bean 没有任何的实际意义,知识为了介绍如何装配这些常用的集合类:

value-list-1value-list-2value-list-3value-prop-1value-prop-2value-prop-3value-set-1value-set-2value-set-3value-array-1value-array-2value-array-3
  • 总结:
  • List 属性为对应的 元素进行装配,然后通过多个 元素设值
  • Map 属性为对应的 元素进行装配,然后通过多个 元素设值,只是 entry 包含一个键值对(key-value)的设置
  • Properties 属性为对应的 元素进行装配,通过多个 元素设值,只是 properties 元素有一个必填属性 key ,然后可以设置值
  • Set 属性为对应的 元素进行装配,然后通过多个 元素设值
  • 对于数组而言,可以使用 设置值,然后通过多个 元素设值。

上面看到了对简单 String 类型的各个集合的装载,但是有些时候可能需要更为复杂的装载,比如一个 List 可以是一个系列类的对象,为此需要定义注入的相关信息,其实跟上面的配置没什么两样,只不过加入了 ref 这一个属性而已:

  • 集合注入总结:
  • List 属性使用 元素定义注入,使用多个 元素的 Bean 属性去引用之前定义好的 Bean
  • Map 属性使用 元素定义注入,使用多个 元素的 key-ref 属性去引用之前定义好的 Bean 作为键,而用 value-ref 属性引用之前定义好的 Bean 作为值
  • Set 属性使用 元素定义注入,使用多个 元素的 bean 去引用之前定义好的 Bean

命名空间装配

除了上述的配置之外, Spring 还提供了对应的命名空间的定义,只是在使用命名空间的时候要先引入对应的命名空间和 XML 模式(XSD)文件。

——【① c-命名空间】——

c-命名空间是在 Spring 3.0 中引入的,它是在 XML 中更为简洁地描述构造器参数的方式,要使用它的话,必须要在 XML 的顶部声明其模式:

74a6b388f32efac4c985ecc4b08e355a.png
  • 注意:是通过构造器参数的方式

现在假设我们现在有这么一个类:

package pojo;public class Student { int id; String name; public Student(int id, String name) { this.id = id; this.name = name; } // setter and getter}

在 c-命名空间和模式声明之后,我们就可以使用它来声明构造器参数了:

c-命名空间属性名以 “c:” 开头,也就是命名空间的前缀。接下来就是要装配的构造器参数名,在此之后如果需要注入对象的话则要跟上 -ref(如c:card-ref="idCard1",则对 card 这个构造器参数注入之前配置的名为 idCard1 的 bean)

很显然,使用 c-命名空间属性要比使用 元素精简,并且会直接引用构造器之中参数的名称,这有利于我们使用的安全性。

我们有另外一种替代方式:

我们将参数的名称替换成了 “0” 和 “1” ,也就是参数的索引。因为在 XML 中不允许数字作为属性的第一个字符,因此必须要添加一个下划线来作为前缀。

——【② p-命名空间】——

c-命名空间通过构造器注入的方式来配置 bean,p-命名空间则是用setter的注入方式来配置 bean ,同样的,我们需要引入声明:

9d0d7c569eaa59b5c7a4de004ff1efb7.png

然后我们就可以通过 p-命名空间来设置属性:

我们需要先删掉 Student 类中的构造函数,不然 XML 约束会提示我们配置 元素。

同样的,如果属性需要注入其他 Bean 的话也可以在后面跟上 -ref:

 

——【③ util-命名空间】——

工具类的命名空间,可以简化集合类元素的配置,同样的我们需要引入其声明(无需担心怎么声明的问题,IDEA会有很友好的提示):

53a5da0819a1a5957b747398143e177e.png

我们来看看引入前后的变化:

只是 util-命名空间中的多个元素之一,下表提供了 util-命名空间提供的所有元素:

元素 描述 引用某个类型的 public static 域,并将其暴露为 bean 创建一个 java.util.List 类型的 bean,其中包含值或引用 创建一个 java.util.map 类型的 bean,其中包含值或引用 创建一个 java.util.Properties 类型的 bean 引用一个 bean 的属性(或内嵌属性),并将其暴露为 bean 创建一个 java.util.Set 类型的 bean,其中包含值或引用 引入其他配置文件

在实际开发中,随着应用程序规模的增加,系统中 元素配置的数量也会大大增加,导致 applicationContext.xml 配置文件变得非常臃肿难以维护。

  • 解决方案:让 applicationContext.xml 文件包含其他配置文件即可
  • 使用 元素引入其他配置文件

1.在【src】文件下新建一个 bean.xml 文件,写好基础的约束,把 applicationContext.xml 文件中配置的 元素复制进去

2.在 applicationContext.xml 文件中写入:

3.运行测试代码,仍然能正确获取到 bean:

31c0f17f45e92a571730360bc1743260.png

通过注解装配 Bean

上面,我们已经了解了如何使用 XML 的方式去装配 Bean,但是更多的时候已经不再推荐使用 XML 的方式去装配 Bean,更多的时候回考虑使用注解(annotation) 的方式去装配 Bean。

  • 优势:
  • 1.可以减少 XML 的配置,当配置项多的时候,臃肿难以维护
  • 2.功能更加强大,既能实现 XML 的功能,也提供了自动装配的功能,采用了自动装配后,程序猿所需要做的决断就少了,更加有利于对程序的开发,这就是“约定由于配置”的开发原则

在 Spring 中,它提供了两种方式来让 Spring IoC 容器发现 bean:

  • 组件扫描:通过定义资源的方式,让 Spring IoC 容器扫描对应的包,从而把 bean 装配进来。
  • 自动装配:通过注解定义,使得一些依赖关系可以通过注解完成。

使用@Compoent 装配 Bean

我们把之前创建的 Student 类改一下:

package pojo;import org.springframework.beans.factory.annotation.Value;import org.springframework.stereotype.Component;@Component(value = "student1")public class Student { @Value("1") int id; @Value("student_name_1") String name; // getter and setter}

解释一下:

  • @Component注解:
  • 表示 Spring IoC 会把这个类扫描成一个 bean 实例,而其中的 value 属性代表这个类在 Spring 中的 id,这就相当于在 XML 中定义的 Bean 的 id:,也可以简写成 @Component("student1"),甚至直接写成 @Component ,对于不写的,Spring IoC 容器就默认以类名来命名作为 id,只不过首字母小写,配置到容器中。
  • @Value注解:
  • 表示值的注入,跟在 XML 中写 value 属性是一样的。

这样我们就声明好了我们要创建的一个 Bean,就像在 XML 中写下了这样一句话:

但是现在我们声明了这个类,并不能进行任何的测试,因为 Spring IoC 并不知道这个 Bean 的存在,这个时候我们可以使用一个 StudentConfig 类去告诉 Spring IoC :

package pojo;import org.springframework.context.annotation.ComponentScan;@ComponentScanpublic class StudentConfig {}

这个类十分简单,没有任何逻辑,但是需要说明两点:

  • 该类和 Student 类位于同一包名下
  • @ComponentScan注解:
  • 代表进行扫描,默认是扫描当前包的路径,扫描所有带有 @Component 注解的 POJO。

这样一来,我们就可以通过 Spring 定义好的 Spring IoC 容器的实现类——AnnotationConfigApplicationContext 去生成 IoC 容器了:

ApplicationContext context = new AnnotationConfigApplicationContext(StudentConfig.class);Student student = (Student) context.getBean("student1
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/650914
推荐阅读
相关标签
  

闽ICP备14008679号