Spring-03-配置和依赖注入

Spring-03-配置和依赖注入

mark

1. Spring-配置

1.1 配置别名

mark

  • alias 设置别名 , 为bean设置别名 , 可以设置多个别名
1
2
<!--设置别名:在获取Bean的时候可以使用别名获取-->
<alias name="userT" alias="userNew"/>

1.2 Bean的配置

  • id : 是bean的标识符,要唯一,如果没有配置id,name就是默认标识符
  • name : 可以设置多个别名,可以用逗号,分号,空格隔开
  • class : bean的全限定名=包名+类名
1
2
3
4
5
6
7
8
9
10
11
<!--bean就是java对象,由Spring创建和管理-->
<!--
id 是bean的标识符,要唯一,如果没有配置id,name就是默认标识符
如果配置id,又配置了name,那么name是别名
name可以设置多个别名,可以用逗号,分号,空格隔开
如果不配置id和name,可以根据applicationContext.getBean(.class)获取对象;
class是bean的全限定名=包名+类名
-->
<bean id="hello" name="hello2 h2,h3;h4" class="com.zhuuu.pojo.Hello">
<property name="name" value="Spring"/>
</bean>

1.3 import

  • 团队的合作通过import实现

mark

  • 实例
1
<import resource="{path}/beans.xml"/>

1.4 Bean 的命名规则

mark

2. 依赖注入(DI)

官方文档位置 : https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-factory-collaborators

mark

两种方式

  1. 构造器注入 (前面已经说过)
  2. set 方法注入 (下面会详细说明)

两种方式区别 :

  • 构造函数用于强制依赖的项目(不可变对象 )
  • setter 方法用于可选性依赖项(可变 可以重新注入)

mark

2.1 概念

  • 依赖注入(Dependency Injection,DI)。
  • 依赖 : 指Bean对象的创建依赖于容器 . Bean对象的依赖资源 .
  • 注入 : 指Bean对象所依赖的资源 , 由容器来设置和装配 .

2.2 Set 注入(重点)

  • 要求被注入的属性,必须要有set方法
  • set方法的方法名由set + 属性首字母大写

所有数据类型注入 文档 : https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-collection-elements

mark

环境搭建

  1. 复杂类型 Address.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.zhuuu.pojo;

public class Address {
private String address;


public String getAddress() {
return address;
}

public void setAddress(String address) {
this.address = address;
}


@Override
public String toString() {
return "Address{" +
"address='" + address + '\'' +
'}';
}
}

mark

  1. 用户类 Student.java (涉及所有数据结构类型的注入)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
package com.zhuuu.pojo;

import java.util.*;

public class Student {

private String name;

private Address address;

private String[] books;

private List<String> hobbys;

private Map<String,String> card;

private Set<String> games;

private Properties info;

private String wife;


@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", address=" + address.toString() +
", books=" + Arrays.toString(books) +
", hobbys=" + hobbys +
", card=" + card +
", games=" + games +
", info=" + info +
", wife='" + wife + '\'' +
'}';
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Address getAddress() {
return address;
}

public void setAddress(Address address) {
this.address = address;
}

public String[] getBooks() {
return books;
}

public void setBooks(String[] books) {
this.books = books;
}

public List<String> getHobbys() {
return hobbys;
}

public void setHobbys(List<String> hobbys) {
this.hobbys = hobbys;
}

public Map<String, String> getCard() {
return card;
}

public void setCard(Map<String, String> card) {
this.card = card;
}

public Set<String> getGames() {
return games;
}

public void setGames(Set<String> games) {
this.games = games;
}

public Properties getInfo() {
return info;
}

public void setInfo(Properties info) {
this.info = info;
}

public String getWife() {
return wife;
}

public void setWife(String wife) {
this.wife = wife;
}
}

以上就是搭建一个环境的过程,接下来我们看看每种数据结构如何注入

  1. 常量注入
1
2
3
4
5
6
7
8
9
10
11
12
13
<bean id="student" class="com.zhuuu.pojo.Student">
<!--普通值注入-->
<property name="name" value="朱酱酱"/>
</bean>

测试类:
public class MyTest {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Student student = (Student) context.getBean("student");
System.out.println(student.getName());
}
}
  1. Bean引用类型注入
1
2
3
4
5
<bean id="address" class="com.zhuuu.pojo.Address"/>
<bean id="student" class="com.zhuuu.pojo.Student">
<property name="name" value="小明"/>
<property name="address" ref="addr"/>
</bean>
  1. 数组注入(array)
1
2
3
4
5
6
7
8
<!--数组类型注入-->
<property name="books">
<array>
<value>红楼梦</value>
<value>西游记</value>
<value>三国演义</value>
</array>
</property>
  1. List注入
1
2
3
4
5
6
7
8
<!--List注入-->
<property name="hobbys">
<list>
<value>敲代码</value>
<value>看电影</value>
<value>听歌</value>
</list>
</property>
  1. Map注入
1
2
3
4
5
6
7
<!--Map注入-->
<property name="card">
<map>
<entry key="身份证" value="1"/>
<entry key="银行卡" value="2"/>
</map>
</property>
  1. set 集合注入
1
2
3
4
5
6
7
8
<!--Set注入-->
<property name="games">
<set>
<value>LOL</value>
<value>COC</value>
<value>BOB</value>
</set>
</property>
  1. null值注入
1
2
3
4
<!--NUll注入-->
<property name="wife">
<null/>
</property>
  1. Properties 配置注入
1
2
3
4
5
6
7
8
<!--Properties注入-->
<property name="info">
<props>
<prop key="学号">121801</prop>
<prop key="准考证号">121801</prop>
<prop key="性别"></prop>
</props>
</property>

小结测试:

1
2
3
4
5
6
7
public class MyTest {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Student student = (Student) context.getBean("student");
System.out.println(student.toString());
}
}

结果

1
2
3
4
5
6
7
8
9
10
Student{name='朱酱酱', 
address=Address{address='null'},
books=[我是你爸爸, 西游记, 三国演义],
hobbys=[听歌, 敲代码, 看电影],
card={身份证=3201, 驾照=3201},
games=[LOL, CDC],
info={学号=1212, ID=1231, 性别=男},
wife='null'}

Process finished with exit code 0

3. P命名和C命名注入

  1. User.java(注意:这里没有有参构造器)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class User {
private String name;
private int age;

public void setName(String name) {
this.name = name;
}

public void setAge(int age) {
this.age = age;
}

@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}

3.1 P命名空间注入(property 缩写)

  1. 需要在头文件中加入约束文件
1
2
3
4
导入约束 : xmlns:p="http://www.springframework.org/schema/p"

<!--P(属性: properties)命名空间 , 属性依然要设置set方法-->
<bean id="user" class="com.zhuuu.pojo.User" p:name="朱酱酱" p:age="18"/>

结果:

mark

官方文档:

mark

3.2 C命名空间注入(构造器注入)

官方文档 : https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-c-namespace

mark

  1. 需要在头文件中加入约束文件
1
2
3
4
导入约束 : xmlns:c="http://www.springframework.org/schema/c"

<!--C(构造: Constructor)命名空间 , 属性依然要设置set方法-->
<bean id="user" class="com.zhuuu.pojo.User" c:name="朱酱酱" c:age="18"/>
  1. 发现问题:爆红了,刚才我们没有写有参构造!
1
2
3
4
public User(String name, int age) {
this.name = name;
this.age = age;
}
  1. 解决:把有参构造器加上,这里也能知道,c 就是所谓的构造器注入!
1
2
3
4
5
6
@Test
public void test02(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User) context.getBean("user");
System.out.println(user);
}

4. Bean 作用域

官方文档 : https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-factory-scopes

mark

  • 在Spring中,那些组成应用程序的主题及由Spring IOC容器所管理的对象,被称之为Bean。
  • 简单来说,bean就是由IOC容器初始化,装配及管理的对象。

mark

几种作用域中,request、session作用域仅在基于web的应用中使用(不必关心你所采用的是什么web应用框架),只能用在基于web的Spring ApplicationContext环境。

4.1 Singleton

mark

  • 当一个bean的作用域为Singleton,那么Spring IoC容器中只会存在一个共享的bean实例,并且所有对bean的请求,只要id与该bean定义相匹配,则只会返回bean的同一实例。
  • Singleton是单例类型,就是在创建起容器时就同时自动创建了一个bean的对象,不管你是否使用,他都存在了,每次获取到的对象都是同一个对象
  • 注意,Singleton作用域是Spring中的默认作用域

要在XML中将bean定义成singleton,可以这样配置:

1
<bean id="ServiceImpl" class="cn.csdn.service.ServiceImpl" scope="singleton">

测试:

1
2
3
4
5
6
7
@Test
public void test03(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User) context.getBean("user");
User user2 = (User) context.getBean("user");
System.out.println(user==user2);
}

4.2 Prototype

mark

  • 当一个bean的作用域为Prototype,表示一个bean定义对应多个对象实例。Prototype作用域的bean会导致在每次对该bean请求(将其注入到另一个bean中,或者以程序的方式调用容器的getBean()方法)时都会创建一个新的bean实例
  • Prototype是原型模式,它允许我们每次获取到的对象都不是同一对象
  • 根据经验,对有状态的bean应该是用prototype作用域,而对无状态的bean应该采用singleton作用域(重要)。

在XML中将bean定义成prototype,可以这样配置:

1
2
3
<bean id="account" class="com.foo.DefaultAccount" scope="prototype"/>  
或者
<bean id="account" class="com.foo.DefaultAccount" singleton="false"/>

注意 : prototypesingleton

mark

4.3 Request(一次HTTP请求)

mark

注意 : 要使用XmlwebApplicationContext,使用 ClassPathXmlApplication会抛出异常

mark

  • 当一个bean的作用域为Request,表示在一次HTTP请求中,一个bean定义对应一个实例;即每个HTTP请求都会有各自的bean实例

  • 该作用域仅在基于webSpring ApplicationContext情形下有效。

1
<bean id="loginAction" class=cn.csdn.LoginAction" scope="request"/>
  • 针对每次HTTP请求,Spring容器会根据loginAction bean的定义创建一个全新的LoginAction bean实例,且该loginAction bean实例仅在当前HTTP request内有效。

  • 因此可以根据需要放心的更改所建实例的内部状态,而其他请求中根据loginAction bean定义创建的实例,将不会看到这些特定于某个请求的状态变化。

  • 当处理请求结束,request作用域的bean实例将被销毁。

4.4 Session(一次Session中)

  • 当一个bean的作用域为Session,表示在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效
1
<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>
  • 针对某个HTTP SessionSpring容器会根据userPreferences bean定义创建一个全新的userPreferences bean实例,且该userPreferences bean仅在当前HTTP Session内有效。

  • request作用域一样,可以根据需要放心的更改所创建实例的内部状态,而别的HTTP Session中根据userPreferences创建的实例,将不会看到这些特定于某个HTTP Session的状态变化。

  • HTTP Session最终被废弃的时候,在该HTTP Session作用域内的bean也会被废弃掉。

4.5 Application

mark

打赏
  • 版权声明: 本博客所有文章除特别声明外,均采用 Apache License 2.0 许可协议。转载请注明出处!
  • © 2019-2022 Zhuuu
  • PV: UV:

请我喝杯咖啡吧~

支付宝
微信