本章内容
Spring 依赖注入
Spring 注入内部Bean
Spring 注入集合
Spring 依赖注入
什么是依赖注入?
-
依赖注入(
Dependency Injection, DI
),便于管理和测试应用程序
实现原理:
-
在
Java
程序中当一个Java
示例需要调用另一个Java
实例的方法的时候需要手动new
一个对象,通过对象去调用它的方法。 -
Spring
框架中,被调用者实例由Spring
容器创建,不再是调用者创建。这一过程被称为控制反转
Spring
实现过程:
-
Spring
容器在创建被调用者的实例时会自动将调用者需要的对象实例注入给调用者。 -
调用者通过
Spring
容器获得被调用者实例
依赖注入的实现方式
设值注入(
setter
)构造函数注入
构造函数注入:
概念:
IoC
容器使用构造函数注意被依赖的实例。每一个参数代表一个依赖
setter
注入:
概念:
IoC
容器使用setter
方法注入被依赖实例。
实现原理:
调用无参构造器或无参static
工厂方法实例化Bean
后,调用该Bean
的setter
方法
Spring
实例化Bean
的过程:
-
调用默认的(无参)构造方法实例化
Bean
-
通过
Java
反射机制调用对应的setXxx()
方法为属性注入值
由上述可知setter
注入的条件:
-
提供一个默认的无参构造方法
-
为需要注入的属性提供对应的
set
方法
在Spring
配置文件中的使用:
-
为属性注入值:使用
<bean>
的子元素<property>
-
构造注入值:使用
<constructor-arg>
标签定义构造方法。使用value
设置该参数的值
构造函数注入
实现:
-
使用
<constructor-age>
标签实现构造函数注入
标签包含ref
、value
、type
、index
等属性。value
属性用于注入基本数据类型以及字符串类型的值;ref
属性用于注入已经定义好的 Bean
;type
属性用来指定对应的构造函数,当构造函数有多个参数时,使用index
属性指定参数的位置,index
属性值从 0 开始。
示例:
-
重构
MainApp
类,新增Person
和Main
类
Man
:
package com.bean;
/**
* @description:Man类作为一个基类也是一个Bean对象
* @data: 2021/11/17 16:02
* @author: Lucfier
*/
public class Man {
private String name;
private int age;
/* 提供set和get方法 */
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
/* 提供show方法 */
public void show() {
System.out.println("名称 :" + name + "\n年龄 :" + age);
}
/* 提供空参和带参构造方法 */
public Man(){
System.out.println("在Man的构造函数内!");
}
public Man(String name, int age) {
System.out.println("在Man的带参构造函数内!");
this.name = name;
this.age = age;
}
}
Person
:
package com.bean;
/**
* @description:创建Person类作为一个新增的Bean类
* @data: 2021/11/17 16:00
* @author: Lucifer
*/
public class Person {
private Man man;
public Person(Man man) {
System.out.println("在Person的有参构造器内!");
this.man = man;
}
public void man() {
man.show();
}
}
MainApp
:
package com.junkingboy;
import com.bean.Person;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @description:获取Spring当中的Bean.xml配置文件下的类和属性信息
* @data: 2021/11/15 11:20
* @author: Lucifer
*/
public class MainApp {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
Person person = (Person) context.getBean("person");
person.man();
}
}
Beans.xml
:
结论:
-
出现的顺序是会先初始化
Man
的Bean
对象,因为在Person
的Bean
对象里面引用了Man
的Bean
配置。 -
<constructor-age>
标签设置的值相当于定义了两个形参去实例化Man
类,通过Man
类的带参构造器。 -
构造好了
Man
类的对象以后由于Person person
会将Man
对象作为参数带到Person
类的带参构造器中。 -
在使用
Person
构造器返回的Man
类对象调用Man
下的Show()
方法
setter注入
实现:
-
使用
<property>
标签
标签包含name
、ref
、value
等属性。name
用于指定参数名称;value
属性用于注入基本数据类型以及字符串类型的值;ref
属性用于注入已经定义好的Bean
。
示例:
-
修改
Person
类
package com.bean;
/**
* @description:创建Person类作为一个新增的Bean类
* @data: 2021/11/17 16:00
* @author: Lucifer
*/
public class Person {
private Man man;
/* 提供get和set方法 */
public Man getMan() {
return man;
}
public void setMan(Man man) {
System.out.println("在setMan方法内!");
this.man = man;
}
public void man() {
man.show();
}
}
结论:
-
该写法实际在
Bean
的初始化顺序和上一个写法没区别 -
在
Spring Bean
处使用的标签和上一个有所不同
Spring注入内部Bean
什么是Spring
内部Bean
?
-
在
Java
类内部定义的类称为内部类,在Spring
的Bean
内部定义的Bean
称为Spring
内部Bean
特点:
-
不需要指定
id
和name
。如果指定了,容器不会将其作为区分Bean
的标识符,会无视内部Bean
的scope
属性。所以内部Bean
总是匿名的,而且总是随着外部Bean
创建。
在实际开发中很少注入内部 Bean,因为开发者无法将内部的 Bean 注入外部 Bean 以外的其它 Bean。
实现:
-
注入内部
Bean
使用<property>
和<constructor-arg>
中的<bean>
标签。
示例:
Spring注入集合
概念:
Spring
注入集合的意思是需要传递Java Collection
类型的值
方式:
使用Spring
提供的集合配置标签
标签 | 说明 |
---|---|
<list> |
用于注入 list 类型的值,允许重复 |
<set> |
用于注入 set 类型的值,不允许重复 |
<map> |
用于注入 key-value 的集合,其中 key-value 可以是任意类型 |
<props> |
用于注入 key-value 的集合,其中 key-value 都是字符串类型 |
示例:
-
新建
JavaCollection
类
package com.junkingboy;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
/**
* @description:该类主要是java的list等属性
* @data: 2021/11/17 18:24
* @author: Lucifer
*/
public class JavaCollection {
List manList;
Set manSet;
Map manMap;
Properties manProp;
/* 提供get和set方法 */
public List getManList() {
System.out.println("List Elements :" + manList);
return manList;
}
public Set getManSet() {
System.out.println("Set Elements :" + manSet);
return manSet;
}
public Map getManMap() {
System.out.println("Map Elements :" + manMap);
return manMap;
}
public Properties getManProp() {
System.out.println("Properties Elements :" + manProp);
return manProp;
}
public void setManList(List manList) {
this.manList = manList;
}
public void setManSet(Set manSet) {
this.manSet = manSet;
}
public void setManMap(Map manMap) {
this.manMap = manMap;
}
public void setManProp(Properties manProp) {
this.manProp = manProp;
}
}
Bean.xml
: