Spring-入门(IoC-简化版)

[toc]

0、资料

笔记:

Spring框架-笔记

1、https://blog.csdn.net/weixin_45496190/article/details/107059038
2、https://blog.csdn.net/weixin_45496190/article/details/107067200
3、https://blog.csdn.net/weixin_45496190/article/details/107071204
4、https://blog.csdn.net/weixin_45496190/article/details/107082732
5、https://blog.csdn.net/weixin_45496190/article/details/107092107


1、下载 Spring5

下载教程

下载链接

Maven依赖:(导入以下1个个依赖,会自动导入spring所需的依赖)

1
2
3
4
5
6
7
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.9</version>
</dependency>
</dependencies>

2、入门案例(IOC)

2.1 案例1:(实体类没有成员变量)

案例目标:利用spring创建对象、执行方法。

步骤:

  1. 下载Spring的Jar包(案例中使用jar包:commons.log + spring bean + core + conext + expression)
  2. 创建1个普通的 java项目。
  3. 项目中添加 jar 包依赖。
  4. 创建JavaBean:User
  5. 创建 Spring的配置文件(idea创建的springXML自动生成约束):bean1.xml
  6. 测试Spring效果(Junit)

User类:

1
2
3
4
5
6
7
8
package com.cyw;

public class User {
public void add(){
System.out.println("add方法执行了。。。");
}
}

bean1.xml:(resources资源目录下)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?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">



<!-- bean标签中,
id:唯一标识,随便取;
class:JavaBean 的全类名
-->
<bean id="userbean" class="com.cyw.User"></bean>

</beans>

测试效果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.cyw;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class userTest {
@Test
public void addTest() {
//加载资源
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");

// 获取对象(第1个参数为配置文件中bean标签的id,第2个参数为JavaBean的字节码)
User user = context.getBean("userbean", User.class);
user.add();

}
}

2.2 案例2:(实体类有成员变量)

实体类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.cyw.entity;

public class User {
private String myName;

public String getMyName() {
return myName;
}

public void setMyName(String myName) {
this.myName = myName;
}

public void add(){
System.out.println("add方法执行了。。。");
}
}

beans.xml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?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">

<!-- id是唯一标识,随便起;class是实体类的全类名 -->
<bean id="user" class="com.cyw.entity.User">
<!--
name为实体类的成员变量名,
value为变量值
(value也可以是ref,ref的值为另外一个实体类的bean标签的id)
小结:java自带的类型用value,用户自定义的类型用ref
-->
<property name="myName" value="张三"></property>
</bean>

</beans>

3、IOC 容器

3.1 IOC 简介

1、什么是 IOC ?

IOC也叫控制反转,是面向对象编程中的一种设计原则。在Spring中,IOC指的是==我们把对象的创建和调用交给Spring来管理==。

2、使用 IOC 的目的:解耦

3、IOC的底层:xml 解析、工厂、反射

  • 以下操作均在工厂类中完成。
  • XML解析Spring的配置文件,得到 JavaBean的全类名
  • 利用 Class.ForName(全类名)得到 1个 Class 对象
  • 利用 Class 对象的 newInstance( ) 方法创建对象,并返回。

4、Spring的 IOC接口

  • BeanFactory接口(只能Spring内部使用):加载配置文件时,不创建对象(使用时创建)。
  • ApplicationContext接口(程序员使用):BeanFactory接口的子接口。加载配置时,就创建对象。
1
2
3
4
5
6
7
8
9
// ApplicationContext接口的使用


// 相对路径获取配置文件中的context
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");

// 绝对路径获取配置文件中的context
ApplicationContext context1 = new FileSystemXmlApplicationContext("resources/beans.xml");

3.2 设置 实体类 的成员变量(依赖注入)

依赖注入:

  • 依赖:bean对象的创建过程依赖于容器
  • 注入:bean对象的成员变量的赋值由容器来完成(值先写在配置文件中,由容器读取配置然后赋值)

以下3种方式在beans.xml中设置 ==实体类== 的成员变量:(1种setter、2种构造器)

setter方法(property标签)-设置 实体类 的成员变量【重点】

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
  <bean id="user" class="com.cyw.entity.User">
<!-- name为实体类的成员变量名,value为变量值
name标识的成员变量的类型为普通变量时
-->
<property name="myName" value="张三"/>

<!--
name标识的成员变量的类型为自定义的类型时(Address类)
-->
<property name="myAddress" ref="Address"/>

<!--
name标识的成员变量的类型为 array数组时
-->
<property name="mybooks" >
<array>
<value>西游记</value>
<value>三国演义</value>
<value>红楼梦</value>
</array>
</property>


<!--
name标识的成员变量的类型为 list集合时
-->
<property name="myhobby" >
<list>
<value>唱歌</value>
<value>跳舞</value>
<value>吃饭</value>
</list>
</property>


<!--
name标识的成员变量的类型为 map集合时
-->
<property name="myCard" >
<map>
<entry key="cid" value="001"/>
<entry key="cname" value="张三"/>
<entry key="年龄" value="32"/>
</map>
</property>


<!--
name标识的成员变量的类型为 set集合时
-->
<property name="friends" >
<set>
<value>唱歌</value>
<value>跳舞</value>
<value>吃饭</value>
</set>
</property>


<!--
name标识的成员变量的类型为 null时
-->
<property name="email" >
<null/>
</property>


<!--
name标识的成员变量的类型为 properties配置文件时
-->
<property name="myProp" >
<props>
<prop key="姓名">张三</prop>
<prop key="年龄">24</prop>
</props>
</property>

</bean>

构造器-设置 实体类 的成员变量(按:参数名)

1
2
3
4
<bean id="user" class="com.cyw.entity.User">
<constructor-arg name="myName" value="王五"/>
<constructor-arg name="age" value="22"/>
</bean>

构造器-设置 实体类 的成员变量(按:参数下标)

1
2
3
4
5
<bean id="user" class="com.cyw.entity.User">
<!-- index为实体类的构造函数的参数下标,value为参数值 -->
<constructor-arg index="0" value="李四"/>
<constructor-arg index="1" value="26"/>
</bean>

构造器-设置 实体类 的成员变量(按:参数类型)【不推荐使用】

1
2
3
4
<bean id="user" class="com.cyw.entity.User">
<constructor-arg type="java.lang.String" value="王五"/>
<constructor-arg type="int" value="32"/>
</bean>

4、Spring 的配置

4.1 实体类的别名

填写的位置:beans.xml文件

取别名的2种方式:

  • bean 标签的 name属性
  • alias 标签
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?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">


<!--
(第一种取别名的方式)
bean标签的 name属性来取别名(name可以取多个别名,且别名之间用符号分隔【分隔符:空格、逗号、分号】)
- 以下示例中的 U和Us都是别名
-->
<bean id="user" class="com.cyw.entity.User" name="U,Us">
<constructor-arg name="myName" value="王五"/>
<constructor-arg name="age" value="22"/>
</bean>
<!--
(第二种取别名的方式)
alias标签:取别名
- name:上面的bean标签中的实体类的id
- alias: 用户自己取的别名,取完后,凡是使用实体类id的地方都可以用别名来替换
-->
<alias name="user" alias="U"/>

</beans>

4.2 导入多个配置文件

使用场景:团队开发时使用

前提:存在多个实体类的xml配置文件,想要导入到1个配置文件中,代码只加载汇总后的配置文件

发生的位置:beans.xml(正规的名字是:ApplicationContext.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?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">



<bean id="user" class="com.cyw.entity.User" name="U,U2">
<constructor-arg name="myName" value="王五"/>
<constructor-arg name="age" value="22"/>
</bean>

<!--
导入配置文件
-->
<import resource="bean1.xml"/>
<import resource="bean2.xml"/>
<import resource="bean3.xml"/>
</beans>

5、p命名空间、c命名空间的依赖注入

p命名空间、c命名空间是为了简化 3.2 小节的依赖注入。

5.1 p命名空间

p命名空间的作用:(简化 set 方式的依赖注入)将bean标签的子标签property 以 bean标签属性的形式出现。

使用 p命名空间

1
2
3
4
5
6
7
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<!-- results in a setDriverClassName(String) call -->
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>

p命名空间的使用步骤:

  • 导入命名空间( xmlns:p="http://www.springframework.org/schema/p"
  • 在 bean 标签中使用(如: p:password="root"

使用 p命名空间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<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="myDataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close"
p:driverClassName="com.mysql.jdbc.Driver"
p:url="jdbc:mysql://localhost:3306/mydb"
p:username="root"
p:password="root"/>

</beans>

5.2 c命名空间

c命名空间的作用:(简化 构造器 方式的依赖注入)

c命名空间的使用步骤:

  • 前提:在实体类中已经定义好了 有参构造函数。

  • 导入命名空间( xmlns:c="http://www.springframework.org/schema/c"

  • 在 bean 标签中使用(如: c:email="123",其中的email为构造函数的参数名)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">


<bean id="thingOne" class="x.y.ThingTwo"/>

<!-- 传统方式-->
<bean id="thingOne" class="x.y.ThingOne">
<constructor-arg ref="thingTwo"/>
<constructor-arg value="[emailprotected]"/>
</bean>

<!-- c命名空间方式 -->
<bean id="thingOne" class="x.y.ThingOne" c:thingTwo-ref="thingTwo" c:email="[emailprotected]"/>

</beans>

6、Bean的作用域

Scope Description
singleton **(默认)**将每个 Spring IoC 容器的单个 bean 定义范围限定为单个对象实例。
prototype 将单个 bean 定义的作用域限定为任意数量的对象实例。
request 将单个 bean 定义的范围限定为单个 HTTP 请求的生命周期。也就是说,每个 HTTP 请求都有一个在单个 bean 定义后面创建的 bean 实例。仅在可感知网络的 Spring ApplicationContext中有效。
session 将单个 bean 定义的范围限定为 HTTP Session的生命周期。仅在可感知网络的 Spring ApplicationContext上下文中有效。
application 将单个 bean 定义的范围限定为ServletContext的生命周期。仅在可感知网络的 Spring ApplicationContext上下文中有效。
websocket 将单个 bean 定义的范围限定为WebSocket的生命周期。仅在可感知网络的 Spring ApplicationContext上下文中有效。

使用示例( bean标签的 scope属性):resources/beans.xml

1
2
3
4
5
6
7
8
9
10
11
<bean id="user" class="com.cyw.User" scope="singleton"/>

<bean id="user" class="com.cyw.User" scope="prototype"/>

<bean id="user" class="com.cyw.User" scope="request"/>

<bean id="user" class="com.cyw.User" scope="session"/>

<bean id="user" class="com.cyw.User" scope="application"/>

<bean id="user" class="com.cyw.User" scope="websocket"/>

7、自动装配

自动装配:spring 在context 中自动查找属性,并给 bean 的属性 赋值。

Spring 的 三种装配方式:

  1. XML 中手动配置
  2. java注解手动配置
  3. 自动装配(重要

自动装配的模式(bean标签的 autowire 属性的取值):

Mode Explanation
no (默认)无自动装配。 Bean 引用必须由ref元素定义。对于大型部署,建议不要更改默认设置,因为明确指定协作者可以提供更好的控制和清晰度。在某种程度上,它记录了系统的结构。
byName 按属性名称自动布线。 Spring 寻找与需要自动装配的属性同名的 bean。例如,如果一个 bean 定义被设置为 byName自动装配,并且包含一个master属性(即,它具有setMaster(..)方法),那么 Spring 将查找一个名为master的 bean 定义并使用它来设置属性。
byType 如果容器中恰好存在一个该属性类型的 bean,则使该属性自动装配。如果存在多个错误,则会引发致命异常,这表明您可能不对该 bean 使用byType自动装配。如果没有匹配的 bean,则什么也不会发生(未设置该属性)。
constructor 类似于byType,但适用于构造函数参数。如果容器中不存在构造函数参数类型的一个 bean,则将引发致命错误。

7.1 XML自动装配

bean 标签的 autowire属性

1
2
3
4
5
<bean id="dog" class="com.cyw.Dog"/>

<bean id="user" class="com.cyw.User" autowire="byName">
<property name="name" value="大白">
</bean>

7.1 注解自动装配