Spring 是包含了众多工具方法的 IoC 容器
(1)容器
容器是用来容纳某种物品的基本装置,比如List/Map就是数据存储容器,Tomcat就是Web容器
(2)loC
1. 概述
loC:Inversion if Control(控制反转),也就是说Spring 是一个“控制反转”的容器,是 Spring 的核心思想
eg. 在类上添加@RestController 和 @Controller 注解,就是把这个对象交给 Spring管理,Spring 框架启动时就会加载该类,即实现了把对象交给Spring管理
这部分代码就是loC容器做的事
IoC容器的优点:
资源不由使用资源的双方管理,而由不使用资源的第三方管理,这可以带来很多好处。第一,资源集中管理,实现资源的可配置和易管理。第二,降低了使用资源双方的依赖程度,也就是我们说的耦合度。
代码方面理解:把材料外包出去,不自己制造
2. 使用
【1】Bean的存储
Spring 是一个loC容器,而作为容器,那【存】和【取】的功能就是最基本的。
Spring 容器 管理的主要是对象,这些对象, 我们称之为"Bean"。我们把这些对象交由Spring管理, 由Spring来负责对象的创建和销毁. 我们程序只需要告诉Spring,哪些需要存,以及如何从Spring中取出对象
对于 Spring 框架而言,共有两类注解可以将某个对象交给loC容器管理
Bean 的 名称:Spring bean 是Spring框架在运行时管理的对象,Spring 会给管理的对象起一个名字,而根据这个名称(BeanId)就可以获取到对应的对象
Bean的命名约定:程序开发人员不需要为bean指定名称(BeanId), 如果没有显式的提供名称(BeanId),Spring容器将为该bean生成唯?的名称
命名约定使用Java标准约定作为实例字段名. 也就是说,bean名称以小写字母开头,然后使用驼峰式大小写
- 类名: UserController, Bean的名称为:userController
- 类名: AccountManager, Bean的名称为:accountManager
也有?些特殊情况, 当有多个字符并且第?个和第?个字符都是大写时, 将保留原始的大小写
- 类名: UController, Bean的名称为:UController
- 类名: AManager, Bean的名称为:AManager
@Controller(控制器存储)
@Controller
public class UserController {
public void sayHi(){
System.out.println("这是UserController");
}
}
@SpringBootApplication
public class demo {
public static void main(String[] args) {
//获取Spring上下文对象
ApplicationContext context = SpringApplication.run(demo.class, args);
//从上下文中获取对象,下面是三种不同的获取方式
//根据类的类型获取
UserController userController1 = context.getBean(UserController.class);
//根据名称获取,需要强转
UserController userController2 = (UserController) context.getBean("userController");
//根据名称和类型获取,不需要强转
UserController userController3 = context.getBean("userController", UserController.class);
System.out.println(userController1);
System.out.println(userController2);
System.out.println(userController3);
}
}
获取bean对象, 是父类BeanFactory提供的功能
@Service(服务存储)
@Service
public class UserService {
public void sayHi(){
System.out.println("这是UserService");
}
}
@SpringBootApplication
public class demo {
public static void main(String[] args) {
//获取Spring上下文对象
ApplicationContext context = SpringApplication.run(demo.class, args);
UserService service = context.getBean(UserService.class);
service.sayHi();
}
}
@Repository(仓库存储)、@Configuration(配置存储)、@Component(组件存储)的操作与上述都类似,只需要更改注解
@SpringBootApplication
public class SpringIocDemoApplication {
public static void main(String[] args) {
//获取Spring上下?对象
ApplicationContext context = SpringApplication.run(SpringIocDemoApplicatio
//从Spring上下?中获取对象
UserConfiguration userConfiguration = context.getBean(UserConfiguration.cl
//使?对象
userConfiguration.sayHi();
}
}
为什么需要这么多的注解???
让程序员看到类注解之后,就能直接了解当前类的用途
应用分层的调用逻辑
方法注解 @Bean
类注解是添加到某个类上的, 但是存在两个问题:
使用时的注意点:
@Configuration
public class BeanConfig {
@Bean
public UserInfo userInfo(){
UserInfo user = new UserInfo();
user.setName("zhangsan");
user.setAge(18);
return user;
}
}
定义多个对象
@Configuration
public class BeanConfig {
@Bean
public UserInfo userInfo1(){
UserInfo user = new UserInfo();
user.setName("zhangsan");
user.setAge(18);
return user;
}
@Bean
public UserInfo userInfo2(){
UserInfo user = new UserInfo();
user.setName("lisi");
user.setAge(22);
return user;
}
}
@SpringBootApplication
public class St20231205Application {
public static void main(String[] args) {
//根据名称获取Bean对象
UserInfo userInfo1 = (UserInfo) context.getBean("userInfo1");
UserInfo userInfo2 = (UserInfo) context.getBean("userInfo2");
System.out.println(userInfo1);
System.out.println(userInfo2);
}
}
重命名Bean
@Bean(name = {"u1","user1"})
public User user1(){
User user = new User();
user.setName("zhangsan");
user.setAge(18);
return user;
}
@SpringBootApplication
public class SpringIocDemoApplication {
public static void main(String[] args) {
//获取Spring上下?对象
ApplicationContext context = SpringApplication.run(SpringIocDemoApplicatio
//从Spring上下?中获取对象
User u1 = (User) context.getBean("u1");
//使?对象
System.out.println(u1);
}
}
name={} 可以省略,如下代码所示,如:
@Bean({“u1”,“user1”})
public User user1(){
????????? User user = new User();
????????? user.setName(“zhangsan”);
????????? user.setAge(18);
????????? return user;
}
只有?个名称时, {}也可以省略, 如:
@Bean(“u1”)
public User user1(){
????????? User user = new User();
????????? user.setName(“zhangsan”);
????????? user.setAge(18);
????????? return user;
}
(3)DI
1. 概述
DI: Dependency Injection(依赖注入),即容器在运行期间, 动态的为应用程序提供运行时所依赖的资源,如果程序运行时需要某个资源(对象),此时容器就为其提供这个资源。
所以,DI 和 loC是从不同的角度去描述同一件事情,即都是通过引入loC容器,利用依赖关系注入的方式,实现对象之间的解耦。loC是一种思想,而DI是loC的一种具体实现
依赖注入是?个过程,是指IoC容器在创建Bean时, 去提供运行时所依赖的资源,而资源指的就是对象
2. 使用
关于依赖注入,Spring也给我们提供了三种方式:
(1)属性注入
属性注入是使用 @Autowired 实现的,将 Service 类注入到 Controller 类中
@Controller
public class UserController {
@Autowired
private UserService userService;
public void sayHi() {
System.out.println("Hi,UserController");
userService.sayHi();
}
}
@Service
public class UserService {
public void sayHi() {
System.out.println("Hi,UserService");
}
}
@SpringBootApplication
public class demo {
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(demo.class, args);
UserController userController = (UserController)context.getBean("userController");
userController.sayHi();
}
}
(2)构造方法注入
@Controller
public class UserController2 {
private UserService userService;
@Autowired
public UserController2(UserService userService){
this.userService = userService;
}
public void sayHi() {
System.out.println("Hi,UserController2");
userService.sayHi();
}
}
(3)Setter注入
@Controller
public class UserController3 {
//注??法3: Setter?法注?
private UserService userService;
@Autowired
public void setUserService(UserService userService) {
this.userService = userService;
}
public void sayHi(){
System.out.println("hi,UserController3...");
userService.sayHi();
}
}
(4)三种注入优缺点分析
(4)@Autowired存在问题
当同?类型存在多个bean时,使用@Autowired会存在问题。
解决方法
@Component
public class BeanConfig {
@Primary //指定该bean为默认bean的实现
@Bean("u1")
public User user1(){
User user = new User();
user.setName("zhangsan");
user.setAge(18);
return user;
}
@Bean
public User user2() {
User user = new User();
user.setName("lisi");
user.setAge(19);
return user;
}
}
```java
@Controller
public class UserController {
@Qualifier("user2") //指定bean名称
@Autowired
private User user;
public void sayHi(){
System.out.println("hi,UserController...");
System.out.println(user);
}
}
@Controller
public class UserController {
@Resource(name = "user2")
private User user;
public void sayHi(){
System.out.println("hi,UserController...");
System.out.println(user);
}
}
@Autowird 与 @Resource的区别
- @Autowired 是spring框架提供的注解,?@Resource是JDK提供的注解
- @Autowired 默认是按照类型注入,而@Resource是按照名称注?. 相比于 @Autowired 来说,@Resource 支持更多的参数设置,例如 name 设置,根据名称获取 Bean
Spring:简单来说,Spring 是?个开发应用框架,什么样的框架呢,有这么几个标签:轻量级、?站式、模块化,其目的是用于简化企业级应用程序开发
Spring的主要功能: 管理对象,以及对象之间的依赖关系, ?向切?编程, 数据库事务管理, 数据访问,web框架支持等
但是Spring具备高度可开放性, 并不强制依赖Spring, 开发者可以自由选择Spring的部分或者全
部,Spring可以无缝继承第三方框架,比如数据访问框架(Hibernate 、JPA),web框架(如Struts、JSF)
Spring MVC:Spring MVC是Spring的?个子框架, Spring诞生之后,?家觉得很好用,于是按照MVC模式设计了?个 MVC框架(一些用Spring 解耦的组件), 主要用于开发WEB应用和网络接口,所以,Spring MVC 是?个Web框架
Spring MVC基于Spring进行开发的, 天生的与Spring框架集成. 可以让我们更简洁的进行Web层开发, 支持灵活的 URL 到页面控制器的映射, 提供了强大的约定大于配置的契约式编程支持, 非常容易与其他视图框架集成,如 Velocity、FreeMarker等
Spring Boot:Spring Boot是对Spring的?个封装, 为了简化Spring应用的开发而出现的,中小型企业,没有成本研究自己的框架, 使用Spring Boot 可以更加快速的搭建框架, 降级开发成本, 让开发人员更加专注于Spring应用的开发,而无需过多关注XML的配置和?些底层的实现
Spring Boot 是个脚?架, 插拔式搭建项目, 可以快速的集成其他框架进来
Spring MVC和Spring Boot都属于Spring,Spring MVC 是基于Spring的?个MVC 框架,?Spring Boot 是基于Spring的?套快速开发整合包