Spring5

简介

Spring的理念:使现有的技术更加容易使用,本身是一个大杂烩,整合了现有的技术框架

  • Spring是一个开源的免费框架
  • Spring是一个轻量级的、非侵入式的框架
  • 重要特性:IoC(控制反转)、AOP(面向切面编程)
  • 支持事务的处理。支持整合框架

IoC理论

控制反转(IoC,Inversion of Control)是一种思想,由主动地编程转变为被动地接收。

传统的方式使用面向对象编程,对象的创建对象间的依赖关系完全硬编码在程序中,由程序自己控制:

1
2
3
4
5
6
7
8
9
public class UserServiceImpl implements UserService {
// 传统的方式,程序创建的具体实现类的对象由代码本身决定
private UserDao userDao = new UserDaoMysqlImpl();

@Override
public void getUser() {
userDao.getUser();
}
}

利用set实现 动态值的注入,将获取依赖对象的控制权从程序本身交给用户大大降低了系统的耦合性,可以更加专注在业务的实现上

1
2
3
4
5
6
7
8
9
10
11
12
13
public class UserServiceImpl implements UserService {
private UserDao userDao;

// 利用set实现 动态值的注入
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}

@Override
public void getUser() {
userDao.getUser();
}
}

image-20230525210004436


IoC本质

控制反转是一种通过描述XML注解)并通过第三方去生产或获取特定对象的方式。在Spring中,实现控制反转的是IoC容器,其实现方法是依赖注入DI,Dependency Injection)。

  • 控制:传统应用程序的对象由程序本身控制创建,使用Spring后,对象由Spring来创建。

  • 反转:程序本身不创建对象,变成了被动地接收对象

  • 依赖:bean对象的创建依赖于容器

  • 注入:bean对象中的所有属性,由容器来注入


IoC创建对象的方式

导包

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

默认使用无参构造创建对象

1
2
3
4
<!-- 无参构造 -->
<bean id="user" class="com.hunter.pojo.User">
<property name="name" value="hunter"/>
</bean>

使用有参构造创建对象

1
2
3
4
5
6
7
8
9
10
<!-- 有参构造函数,根据下标赋值 -->
<bean id="user" class="com.hunter.pojo.User">
<constructor-arg index="0" value="hunter"/>
</bean>


<!-- 有参构造函数,根据参数名赋值 -->
<bean id="user" class="com.hunter.pojo.User">
<constructor-arg name="name" value="hunter"/>
</bean>

Bean默认的作用域Singleton(单例)模式下配置文件加载的时候,容器中管理的所有对象就已经完成了初始化。后续getBean的操作直接获取对象。

1
2
3
4
5
6
7
8
@Test
public void test_spring() {
// 获取Spring的上下文对象,app-context.xml中的所有对象完成初始化
ApplicationContext context = new ClassPathXmlApplicationContext("app-context.xml");

UserService userService = (UserService) context.getBean("userServiceImpl");
userService.getUser();
}

Spring配置

别名

1
2
<!-- name的值为别的bean的id,如果添加了别名,也可以使用别名获取到这个对象 -->
<alias name="user" alias="userNew"/>

Bean的配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!--  使用Spring来创建对象,在Spring中,这些对象称为bean
id: 变量名
class: 类
name: 也是别名,可以同时取多个别名,可以用空格、逗号、分号分隔
-->
<bean id="mysqlImpl" class="com.hunter.dao.UserDaoMysqlImpl"/>
<bean id="sqlServerImpl" class="com.hunter.dao.UserDaoSqlServerImpl"/>

<!-- property相当于给对象中的属性赋值
ref: 引用Spring容器中创建好的对象
value: 具体的值,基本数据类型
-->
<bean id="userServiceImpl" class="com.hunter.service.UserServiceImpl">
<property name="userDao" ref="mysqlImpl"/>
</bean>

<bean id="user" class="com.hunter.pojo.User" name="user2 u2,u3;u4">
<property name="name" value="hunter"/>
</bean>

import

import一般用于团队开发使用,可以将多个配置文件,导入合并成一个

1
2
3
4
<beans ...>
<import resource="beans1.xml"/>
...
</beans>

DI 依赖注入

  • 依赖:bean对象的创建依赖于容器
  • 注入:bean对象中的所有属性,由容器来注入

构造器注入

constructor-arg


Set方式注入

  1. 复杂类型

    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
    public class Address {
    private String address;

    public String getAddress() {
    return address;
    }

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

    // =============================================================================
    public class Student {
    private String name;

    private boolean isMale;

    private Address address;

    private String[] books;

    private List<String> hobbies;

    private Map<String, String> cards;

    private Set<String> games;

    private Properties info;

    //...

    @Override
    public String toString() {
    return "Student{" +
    "name='" + name + '\'' +
    ", isMale=" + isMale +
    ", address=" + address +
    ", books=" + Arrays.toString(books) +
    ", hobbies=" + hobbies +
    ", cards=" + cards +
    ", games=" + games +
    ", info=" + info +
    '}';
    }
    }
  2. beans.xml

    1
    2
    3
    4
    <bean id="student" class="com.hunter.pojo.Student">
    <!-- 普通值注入,使用value -->
    <property name="name" value="黄铁"/>
    </bean>
  3. 完善注入信息

    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
    <bean id="student" class="com.hunter.pojo.Student">
    <!-- 注入普通值,使用value -->
    <property name="name" value="黄铁"/>
    <!-- 注入bean,使用ref -->
    <property name="address" ref="address"/>
    <!-- 注入数组,使用array -->
    <property name="books">
    <array>
    <value>银河帝国</value>
    <value>灌篮高手</value>
    </array>
    </property>
    <!-- 注入List,使用list -->
    <property name="hobbies">
    <list>
    <value>电影</value>
    <value>篮球</value>
    </list>
    </property>
    <!-- 注入Map,使用map -->
    <property name="cards">
    <map>
    <entry key="身份证" value="3303000000000000000"/>
    <entry key="校园卡" value="3002092000002033"/>
    </map>
    </property>
    <!-- 注入Set,使用set -->
    <property name="games">
    <set>
    <value>麻将</value>
    <value>斗地主</value>
    </set>
    </property>

    <!-- 注入null -->
    <property name="girlFriend">
    <null/>
    </property>

    <!-- 注入Properties -->
    <property name="info">
    <props>
    <prop key="driver">com.mysql.cj.jdbc.Driver</prop>
    <prop key="jdbc">jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8</prop>
    </props>
    </property>

    </bean>

    <bean id="address" class="com.hunter.pojo.Address"/>

扩展方式

可以使用p命令空间和c命名空间进行注入。

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"
xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">

<!-- p命令空间注入,可以直接注入属性的值: property -->
<bean id="user" class="com.hunter.pojo.User" p:name="hunter" p:age="30"/>

<!-- c命令空间注入,通过构造器注入:constructor-arg -->
<bean id="user2" class="com.hunter.pojo.User" c:name="hunter" c:age="30"/>

</beans>

Bean的作用域

Scope 描述
singleton
单例模式
(默认) 每次从容器中getBean的时候,都会取相同的一个对象。
prototype
原型模式
每次从容器中getBean的时候,都会产生一个新对象。
request 只在web开发中使用
Scopes a single bean definition to the lifecycle of a single HTTP request. That is, each HTTP request has its own instance of a bean created off the back of a single bean definition. Only valid in the context of a web-aware Spring ApplicationContext.
session 只在web开发中使用
Scopes a single bean definition to the lifecycle of an HTTP Session. Only valid in the context of a web-aware Spring ApplicationContext.
application 只在web开发中使用
Scopes a single bean definition to the lifecycle of a ServletContext. Only valid in the context of a web-aware Spring ApplicationContext.
websocket 只在web开发中使用
Scopes a single bean definition to the lifecycle of a WebSocket. Only valid in the context of a web-aware Spring ApplicationContext.

Bean的自动装配