认识 IoC 容器和 Servlet 容器
- 1.认识容器
- 1.1 IoC 容器
- 1.2 loC 的实现方法
- 1.2.1 依赖注入
- 1.2.2 依赖查找
- 1.3 认识 Servlet 容器
- 2.用 IoC 管理 Bean
- 2.1 创建一个 Bean
- 2.2 编写 User 的配置类
- 2.3 编写测试类
- 3.用 Servlet 处理请求
- 3.1 注册 Servlet 类
- 3.2 开启 Servlet 支持
1.认识容器
1.1 IoC 容器
loC(Inversion of Control
)容器,是面向对象编程中的一种设计原则,意为 控制反转(也被称为 控制反向 或 控制倒置)。它将程序中创建对象的控制权交给 Spring 框架来管理,以便降低计算机代码之间的耦合度。
控制反转的实质是 获得依赖对象的过程 被反转了。这个过程由自身管理变为由 loC 容器主动注入。这正是 loC 实现的方式之一:依赖注入(dependency injection
,DI
),由 loC 容器在运行期间动态地将某种依赖关系注入对象之中。
在传统编程方式中,要实现某种功能一般都需要几个对象相互作用。在主对象中要保存其他类型对象的引用,以便在主对象中实例化对象,然后通过调用这些引用的方法来完成任务,其运行方式如下图所示。
而 IoC 容器是在主对象中设置 Setter 方法,通过调用 Setter 方法或构造方法传入所需引用(即依赖注入),如下图所示。
要使用某个对象,只需要从 IoC 容器中获取需要使用的对象,不需要关心对象的创建过程,即把创建对象的控制权反转给了 Spring 框架。
1.2 loC 的实现方法
loC 的实现方法主要有两种:依赖注入 与 依赖查找。
1.2.1 依赖注入
在软件设计中,依赖 指的是一个类需要调用的其他类或者服务,而 注入 则是指将这些所需的类或服务传递给需要它们的类的过程。使用 依赖注入 技术,我们可以在运行时将依赖关系传递给对象,而不是让对象自己去创建或查找它们需要的依赖。
如此,则软件中的组件可以在不同环境下重复使用,就像家里的电器可以随意在不同的插座上使用一样,不用担心它们的电源问题。依赖注入 让我们的代码更加灵活,更容易维护和扩展。
loC 容器通过类型或名称等信息将不同对象注入不同属性中。组件不做定位查询,只提供普通的 Java 方法让容器去决定依赖关系。这是最流行的 loC 方法。依赖注入主要有以下几种方式。
- 设值注入(
setter injection
):让 loC 容器调用注入所依赖类型的对象。 - 接口注入(
interface injection
):实现特定接口,以供 loC 容器注入所依赖类型的对象。 - 构造注入(
constructor injection
):实现特定参数的构造函数,在创建对象时让 loC 容器注入所依赖类型的对象。 - 基于注解:通过 Java 的注解机制让 loC 容器注入所依赖类型的对象,例如,使用 @Autowired。
loC 是通过第三方容器来管理并维护这些被依赖对象的,应用程序只需要接收并使用 IoC 容器注入的对象。
1.2.2 依赖查找
在传统实现中,需要用户使用 API 来管理依赖的创建、查找资源和组装对象。这会对程序有侵入性。
依赖查找 则通过调用容器提供的 回调接口 和 上下文环境 来获取对象,在获取时需要提供相关的配置文件路径、key
等信息来确定获取对象的状态。依赖查找通常有两个方法:依赖拖拽(DP
)和 上下文依赖查找(CDL
)。
1.3 认识 Servlet 容器
Servlet 是在 javax.servlet
包中定义的一个接口。在开发 Spring Boot 应用程序时,使用 Controller 基本能解决大部分的功能需求。但有时也需要使用 Servlet,比如实现 拦截 和 监听 功能。Spring Boot 的核心控制器 DispatcherServlet 会处理所有的请求。如果自定义 Servlet,则需要进行注册,以便 DispatcherServlet 核心控制器知道它的作用,以及处理请求 url-pattern
。
2.用 IoC 管理 Bean
2.1 创建一个 Bean
创建一个名为 User
的 Bean。
@Data
public class User implements Serializable {private int id;private String name;}
2.2 编写 User 的配置类
编写配置类,并实例化一个对象。
@Configuration
public class UserConfig {//将此返回的值生成一个bean@Bean("user1")public User user() {User user = new User();user.setId(1);user.setName("pipi");return user;}
}
- @Confguration:用于标注配置类,让 Spring 来加载该类配置作为 Bean 的载体。在运行时,将为这些 Bean 生成 BeanDefinition 和服务请求。
- @Bean:产生一个 Bean,并交给 Spring 管理。目的是封装用户、数据库中的数据,一般有 Setter、Getter 方法。
2.3 编写测试类
下面实例化一个 User 对象,然后通过上下文获取 Bean 对象 user1
。
@RunWith(SpringRunner.class)
@SpringBootTest
public class IocTest {@Autowiredprivate ApplicationContext applicationContext;@Testpublic void testIoc() {User user = (User) applicationContext.getBean("user1");System.out.println(user);}
}
- @RunWith(SpringRunner.class):让测试运行于 Spring 测试环境。
- @SpringBootTest:Spring Boot 用于测试的注解,可指定入口类或测试环境等。
- @Test:一个测试方法。
- ApplicationContext:获取 Spring 容器中已初始化的 Bean,这里是
user1
。
运行 testIoC
方法,在控制台输出以下结果:
3.用 Servlet 处理请求
使用 Servlet 处理请求,可以直接通过注解 @WebServlet(urlPattern,descript)
注册 Servlet,然后在入口类中添加注解@ServletComponentScan
,以扫描该注解指定包下的所有 Servlet。
3.1 注册 Servlet 类
package com.example.demo;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** Description: 添加注解进行修饰*/
@WebServlet(urlPatterns = "/ServletDemo02/*")
public class ServletDemo02 extends HttpServlet{/*** Description:* 重写doGet方法,父类的HttpServlet的doGet方法是空的,没有实现任何代码,子类需要重写此方法。*客户使用GET方式请求Servlet时,Web容器调用doGet方法处理请求。*/@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("doGet");resp.getWriter().print("Servlet ServletDemo02");}
}
- @WebServlet(urlPatterns = “/ServletDemo02/*”):属性
urlPatterns
指定 WebServlet 的作用范围,这里代表ServletDemo02
下的所有子路径。 - doGet:父类 HttpServlet 的
doGet
方法是空的,没有实现任何代码,子类需要重写此方法。
3.2 开启 Servlet 支持
在入口类上添加注解 @ServletComponentScan,以使 Servlet 生效。
package com.example.demo;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;@ServletComponentScan
@SpringBootApplication
public class ServletDemoApplication {public static void main(String[] args) {SpringApplication.run(ServletDemoApplication.class, args);}
}
- @ServletComponentScan:组件扫描,可自动发现和装配一些 Bean,并根据定义的扫描路径构符合扫描规则的类装配到 Spring 容器中。
- @SpringBootApplication:入口类 Application 的启动注解。
在运行程序后,使用 GET 方法访问 http://localhost:8080/ServletDemo02/*
,会返回重写 doGET
方法的值:
同时,控制台会输出 doGet 里定义的值: