了解完Spring的基本概念后,我们紧接着来了解Spring中的核心文件--Spring配置文件。
我们在上一节Spring的基本概念中快速使用了一下Spring,其中我们在配置文件中主要涉及到就是Bean标签的配置:主要的配置字段有id, class, scope。 id是Bean的唯一标识不可重复,class是该类的全限定名。scope则是影响范围,有singleton和prototype两个可选项。当选择为singleton时,表示每次问IoC容器索要的对象是同一个,而选择为prototype时,则生成的对象是不同的。读者可分别打印其地址尝试。
此外,scope不同时,对象的创建时机不同,我们可以覆盖构造方法观察构造方法中的输出语句何时打印。
public class HelloWorld { public HelloWorld() { // 覆盖无参构造方法,是为了验证bean的scope分别为singleton和prototype时,创建对象的时机 // 在Test代码中获取IoC容器那一行代码中打断点,执行测试方法 // 当scope=singleton时,IoC容器完成加载时,对象就创建了 // 当scope=prototype时,IoC容器完成加载时,还未创建对象,而是调用getBean方法时创建的 System.out.println("object is creating..."); } public void sayHello() { System.out.println("hello, spring"); } }
谈到构造方法,我们在Spring基本概念中也提到了,Spring容器创建对象的方式是反射。而反射通常是通过无参构造方法实现的,而一个类会自动生成一个默认的无参构造方法。说到这里,已经有一些开发经验的伙伴是否有这样的经历:为一个类创建了一个有参构造方法,此时我们向Spring容器索要对象时提示错误:
因为此时找不到无参的构造方法了,反射创建对象就失败了。包括配置文件也会提醒你:没有合适的构造方法。
此外,还能在配置文件中配置对象的初始化/销毁方法,属性是:init-method/destory-method。由于不常用,我们不再举例。
想象这样一个场景,我们上面的HelloWorld类中有一个成员属性是HelloSpring对象,我们怎么给HelloWorld对象设置这样的一个成员属性对象呢?这需要使用到依赖注入(Dependency Injection,DI),是Spring给对象设置成员变量的方法。有两种实现方式:构造方法和set方法。
HelloWorld类中添加成员对象与包含该属性的有参构造
public class HelloWorld { private HelloSpring helloSpring; public HelloWorld(HelloSpring helloSpring) { this.helloSpring = helloSpring; } public void sayHello() { helloSpring.sayHello(); } }
并在配置文件中添加HelloSpring Bean标签,添加使用构造方法注入helloSpring属性的一行标签
同样添加成员对象与该属性的set方法
public class HelloWorld { private HelloSpring helloSpring; public void sayHello() { helloSpring.sayHello(); } public void setHelloSpring(HelloSpring helloSpring) { this.helloSpring = helloSpring; } }
添加使用set方法注入属性的一行标签
我们注意到这里引用其它对象作为成员变量时,用的关键字是"ref",实际上这里有其它选项:当需要注入的是普通属性如int, float时,应使用"value"关键字;要注入集合属性时,使用"list";要注入map时,使用"map"。这些细碎的知识,大家可以等到使用时去搜索一下,不要硬记,抓大放小,主要是理解大的思想。
可以想象,当项目的功能逐渐增加时,配置文件会变得异常庞大。此时我们可以分模块开发,将配置文件进行拆分。而在主配置文件里使用import标签引入其它配置文件。