当前位置: 首页 > ai >正文

SpringIoCDI

目录

1.前情摘要

1.1 什么是Spring?

1.2 什么是容器?

1.3 什么是Ioc

2.Ioc

2.1 传统设计思想

2.2 解决方案

3.DI介绍

4.IoC和DI的使用

4.1 图书管理代码修改

4.2 依赖注入体现

5.IoC详解

5.1 Bean的存储

5.1.1 @Controller(控制器存储)

5.1.2 @Service(服务存储)

5.1.3 @Repository(仓库存储)

5.1.4 @Component(组件存储)

5.1.5 @Configuration(配置存储)

5.1.7 为什么要分这么多注解

5.2 方法注解@Bean

5.2.1 Bean命名规则

5.2.2获取Bean对象的方式

5.2.3 重命名Bean

5.3 两类注解对比

5.3.1类注解(@Component 全家桶)

5.3.2方法注解(@Bean)

5.3.3核心区别

5.3.4协作关系

5.3.5一句话总结

5.4 扫描路径

6.DI 详解

6.1 属性注入

6.2 构造方法注入

6.3 Setter注入

6.4 三种注解优缺点分析

6.5 @Autowired存在的问题

6.5.1 @Primary

6.5.2 @Qualifier

6.5.3 @Resource

7.总结

7.1 Spring,Spring Boot和Spring MVC的关系及区别

7.2 Bean的命名

7.3 常见面试题


1.前情摘要

1.1 什么是Spring?

Spring是⼀个开源框架,他让我们的开发更加简单.他支持广泛的应用场 景,有着活跃而庞大的社区,这也是Spring能够长久不衰的原因.

Spring是包含了众多工具方法的loC容器

1.2 什么是容器?

容器是用来容纳某种物品的(基本)装置。一来自:百度百科

生活中的水杯,垃圾桶,冰箱等等这些都是容器。

我们想想,之前课程我们接触的容器有哪些?

  • List/Map->数据存储容器

  • Tomcat -> Web 容器

1.3 什么是Ioc

在前面讲到,在类上面添加@RestController @Controller 注解,就是把这个对象交给Spring管理,Spring框架启动时就会加载该类.把对象交 给Spring管理,就是IoC思想.

IoC:Inversion of Control(控制反转),也就是说Spring是一个"控制反转"的容器.

什么是控制反转呢?也就是控制权反转.什么的控制权发生了反转?获得依赖对象的过程被反转了

也就是说,当需要某个对象时,传统开发模式中需要自己通过new创建对象,现在不需要再进行创

建,把创建对象的任务交给容器,程序中只需要依赖注入(DependencyInjection,DI)就可以了.

这个容器称为:loC容器.Spring是一个loC容器,所以有时Spring也称为Spring容器.

控制反转是一种思想,在生活中也是处处体现

比如自动驾驶,传统驾驶方式,车辆的横向和纵向驾驶控制权由驾驶员来控制,现在交给了驾驶自

动化系统来控制,这也是控制反转思想在生活中的实现

比如招聘,企业的员工招聘,入职,解雇等控制权,由老板转交给给HR(人力资源)来处理

2.Ioc

2.1 传统设计思想

先设计轮子(Tire),然后根据轮子的大小设计底盘(Bottom),接着根据底盘设计车身(Framework),最后根据车身设计好整个汽车(Car)。这里就出现了一个"依赖”关系:汽车依赖车身,车身依赖底盘,底盘依赖轮子.

 

public class NewCarExample {public static void main(String[] args) {Car car = new Car(20);car.run();}/*** 汽车对象 */static class Car {private Framework framework;public Car(int size) {framework = new Framework(size);System.out.println("Car init....");}public void run(){System.out.println("Car run...");}}/*** 车⾝类 */static class Framework {private Bottom bottom;public Framework(int size) {bottom = new Bottom(size);System.out.println("Framework init...");}}/*** 底盘类 */static class Bottom {private Tire tire;public Bottom(int size) {this.tire = new Tire(size);System.out.println("Bottom init...");}}/*** 轮胎类 */static class Tire {// 尺寸private int size;public Tire(int size){this.size = size;System.out.println("轮胎尺⼨:" + size);}}
}

从以上代码可以看出,以上程序的问题是:当最底层代码改动之后,整个调用链上的所有代码都需要修改.

程序的耦合度非常高(修改一处代码,影响其他处的代码修改)

2.2 解决方案

在上面的程序中,我们是根据轮子的尺寸设计的底盘,轮子的尺寸一改,底盘的设计就得修改,同样因为我们是根据底盘设计的车身,那么车身也得改,同理汽车设计也得改,也就是整个设计几乎都得改

我们尝试换一种思路,我们先设计汽车的大概样子,然后根据汽车的样子来设计车身,根据车身来设计底盘,最后根据底盘来设计轮子.这时候,依赖关系就倒置过来了:轮子依赖底盘,底盘依赖车身,车身依赖汽车

 

我们可以尝试不在每个类中自己创建下级类,如果自己创建下级类就会出现当下级类发生改变操作,自己也要跟着修改.此时,我们只需要将原来由自己创建的下级类,改为传递的方式(也就是注入的方式),因为我们不需要在当前类中创建下级类了,所以下级类即使发生变化(创建或减少参数),当前类本身也无需修改任何代码,这样就完成了程序的解耦

public class IocCarExample {public static void main(String[] args) {Tire tire = new Tire(20);Bottom bottom = new Bottom(tire);Framework framework = new Framework(bottom);Car car = new Car(framework);car.run();}static class Car {private Framework framework;public Car(Framework framework) {this.framework = framework;System.out.println("Car init....");}public void run() {System.out.println("Car run...");}}static class Framework {private Bottom bottom;public Framework(Bottom bottom) {this.bottom = bottom;System.out.println("Framework init...");}}static class Bottom {private Tire tire;public Bottom(Tire tire) {this.tire = tire;System.out.println("Bottom init...");}}static class Tire {private int size;public Tire(int size) {this.size = size;System.out.println("轮胎尺寸:" + size);}}
}

 

从上面也可以看出来,IoC容器具备以下优点:

汽车建造各个零件对外进行外包,我不需要关心实现的细节,只需要提对应的要求即可

资源不由使用资源的双方管理,而由不使用资源的第三方管理,这可以带来很多好处。第一,资源集中管理,实现资源的可配置和易管理。第二,降低了使用资源双方的依赖程度,也就是我们说的耦合度。

  1. 资源集中管理:IoC容器会帮我们管理一些资源(对象等),我们需要使用时,只需要从IoC容器中去取就可以了

  2. 我们在创建实例的时候不需要了解其中的细节,降低了使用资源双方的依赖程度,也就是耦合度

Spring就是一种loC容器,帮助我们来做了这些资源管理.

依赖注入体现

 

 

3.DI介绍

DI: Dependency Injection(依赖注入)

容器在运行期间,动态的为应用程序提供运行时所依赖的资源,称之为依赖注入。

程序运行时需要某个资源,此时容器就为其提供这个资源。

从这点来看,依赖注入(DI)和控制反转(IoC)是从不同的角度的描述的同一件事情,依赖注入是

从应用程序的角度来描述,就是指通过引入loC容器,利用依赖关系注入的方式,实现对象之间的解

耦.

上述代码中,是通过构造函数的方式,把依赖对象注入到需要使用的对象中的

loC是一种思想,也是"目标",而思想只是一种指导原则,最终还是要有可行的落地方案,而DI就属于

具体的实现。所以也可以说,DI是IoC的一种实现.

比如说我今天心情比较好,吃一顿好的犒劳犒劳自己,那么"吃一顿好的”是思想和目标(是

loC),但最后我是吃海底捞还是杨国福?这就是具体的实现,就是DI。

4.IoC和DI的使用

4.1 图书管理代码修改

Spring是一个IoC(控制反转)容器,作为容器具备的两个最基础的功能就是存和取

Spring容器管理的主要是对象,这些对象称之为"Bean",我们把这些对象交由Spring来管理,由Spring来负责对象的创建和销毁,我们程序只需要告诉Spring,哪些需要寸,以及如何从Spring中取出对象

  1. Service层及Dao层的实现类,交给Spring管理:使用注解:@Component

  2. 在Controller层和Service层注入运行时依赖的对象:使用注解@Autowired

package com.example.demo.controller;import com.example.demo.model.BookInfo;
import com.example.demo.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.List;//控制层:接收前端发送的请求,对请求进行处理,并响应数据//获取图书列表
@RequestMapping("/book")
@RestController
public class BookController {@Autowired//从Spring中取出对象放入private BookService bookService;//依赖注入@RequestMapping("/getList")public List<BookInfo> getList(){//获取数据List<BookInfo> books = bookService.getBookList();return books;}
}

BookService 类标记为 Spring 管理的组件(Bean),交给Spring管理

@Component 注解在这里就是让 BookService 能被 Spring 容器识别和管理,成为整个 Spring 依赖注入、组件管理体系中的一部分,这样后续才能顺利进行 BookService 自身的依赖注入(比如注入 BookDao ),以及被其他组件(比如 BookController )依赖注入使用 。

package com.example.demo.service;import com.example.demo.model.BookInfo;
import com.example.demo.dao.BookDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import java.util.List;
//业务逻辑层:处理具体的业务逻辑。
@Component
public class BookService {@Autowiredprivate BookDao bookDao;public List<BookInfo> getBookList(){//获取数据List<BookInfo> books = bookDao.mockData();//处理页面展示for(BookInfo book:books){if(book.getStatus() == 1) {book.setStatusCN("可借阅");}else{book.setStatusCN("不可借阅");}}return books;}
}
package com.example.demo.dao;import com.example.demo.model.BookInfo;
import org.springframework.stereotype.Component;import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
//数据访问层:负责数据访问操作,包括数据的增、删、改、查
@Component
public class BookDao {public List<BookInfo> mockData() {List<BookInfo> books = new ArrayList<>();for (int i = 0; i < 10; i++) {BookInfo book = new BookInfo();book.setId(i);book.setBookName("书籍" + i);book.setAuthor("作者" + i);book.setCount(i * 5 + 3);book.setPrice(new BigDecimal(new Random().nextInt(100)));book.setPublish("出版社" + i);book.setStatus(1);books.add(book);}return books;}
}

4.2 依赖注入体现

@Autowired 
private BookService bookService; 

依赖注入就体现在借助@Autowired,让 Spring 自动把BookService的实例给BookControllerbookService字段,不用自己手动创建,实现了对象依赖的 “自动装配” 。

@Autowired
private BookDao bookDao;

这段代码里依赖注入体现在通过 @Autowired 注解,让 Spring 容器自动为 BookService 类注入 BookDao 的实例,解耦了 BookServiceBookDao 之间的对象创建依赖关系,符合 Spring 框架依赖注入的设计思想,让代码更易于维护和扩展(比如更换 BookDao 的实现类时,在一定程度上不用改动 BookService 的代码 )。

5.IoC详解

5.1 Bean的存储

交给Spring管理的类

两类注解:

  1. 类注解:@Controller,@Service,@Repository,@Component,@Configuration

  2. 方法注解:@Bean

注解加在类上,告诉 Spring:“这个类是一个组件(Bean),需要被扫描并纳入容器管理”。 (Spring 扫描到以上五大注解后,创建 UserService 的实例,其他组件可通过 @Autowired 注入。)

@Bean 加在方法上,告诉 Spring:“这个方法返回的对象需要注册为 Bean”。

5.1.1 @Controller(控制器存储)

package com.example.demo.controller;import org.springframework.stereotype.Controller;@Controller //将对象存储到Spring中
public class UserController {public void say(){System.out.println("UserController say...");}
}

从Spring容器中获取对象

package com.example.demo;import com.example.demo.controller.UserController;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;@SpringBootApplication
public class Demo2Application {public static void main(String[] args) {//获取Spring上下文对象ConfigurableApplicationContext context = SpringApplication.run(Demo2Application.class, args);//从Spring上下文中获取对象UserController userController = context.getBean(UserController.class);//使用对象userController.say();}}

SpringApplication.run() 方法:

作用:启动SpringBoot应用,创建并返回一个Spring应用上下文(ApplicationContext)

执行流程:

  1. 创建一个Spring应用上下文(相当于一个"Bean容器")

  2. 扫描并注册所有被@Component等注解标记的类为Bean

  3. 自动配置Spring环境(如数据库连接,web服务器等)

  4. 启动嵌入式Web服务器(如果是Web应用)

  5. 返回上下文对象,用于后续操作

UserController userController = context.getBean(UserController.class);

作用:从Spring上下文中获取UserController类型的Bean

关键点:

  • UserController必须被Spring管理(如添加@Controller注解)

  • Spring会返回一个已经初始化并注入依赖的单例Bean

  • 等价于在其他 Bean 中使用 @Autowired 注入 UserController

5.1.2 @Service(服务存储)

package com.example.demo.service;import org.springframework.stereotype.Service;@Service
public class UserService {public void say(){System.out.println("UserService say...");}
}
UserService userService = context.getBean(UserService.class);
UserService userService3 =(UserService) context.getBean("userService");
UserService userService2 = context.getBean("userService", UserService.class);

5.1.3 @Repository(仓库存储)

@Repository
public class UserRepository {public void say(){System.out.println("UserRepository say...");}
}

5.1.4 @Component(组件存储)

@Component
public class UserComponent {public void say(){System.out.println("UserComponent say...");}
}

5.1.5 @Configuration(配置存储)

@Configuration
public class UserConfiguration {public void say(){System.out.println("UserConfiguration say...");}
}

5.1.7 为什么要分这么多注解

与应用分层是呼应的,让程序员看到类注解之后,就能直接了解当前类的用途,

  • @Controller:控制层,接收请求,对请求进行处理,并进行响应.

  • @Servie:业务逻辑层,处理具体的业务逻辑.

  • @Repository:数据访问层,也称为持久层.负责数据访问操作

  • @Configuration:配置层.处理项目中的一些配置信息.

类注解之间的关系

查看@Controller /@Service /@Repository /@Configuration 等注解的源码发现:

其实这些注解里面都有一个注解@Component,说明它们本身就是属于@Component的"子类".

@Component是一个元注解,也就是说可以注解其他类注解,如@Controller,@Service

@Repository等.这些注解被称为aComponent的衍生注解.

@Controller,@Service和@Repository用于更具体的用例(分别在控制层,业务逻辑层,持

久化层),在开发过程中,如果你要在业务逻辑层使用@Component@Service,显然@Service是更

好的选择

5.2 方法注解@Bean

5.2.1 Bean命名规则

 

 

UserController->userCotroller

UController->UController

5.2.2获取Bean对象的方式

UserController userController = context.getBean(UserController.class);
UserController userController2 = (UserController)context.getBean("userController");
UserController userController3 = context.getBean("userController", UserController.class);
方式优点缺点典型场景
getBean(Class)无需记名称,类型安全无法区分同类型不同名称的 Bean单例、类型唯一的 Bean
getBean(String)精准按名称查找需手动强转,类型不安全兼容旧代码、名称唯一的场景
getBean(String, Class)名称 + 类型双重匹配,类型安全需记名称多例、同类型不同名称的 Bean
System.out.println(userController);
System.out.println(userController2);
System.out.println(userController3);

不同的方式拿到的是同一个对象,单例模式的体现


  • 方法注解@Bean注解要配合五大注解使用

package com.example.demo.model;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserInfo {private String name;private Integer age;
}
package com.example.demo.component;import com.example.demo.model.UserInfo;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;@Component
public class UserInfoComponent {@Beanpublic UserInfo userInfo(){return new UserInfo("Jack",18);}
}
package com.example.demo;import com.example.demo.model.UserInfo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;@SpringBootApplication
public class Demo2Application {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(Demo2Application.class, args);UserInfo userInfo = context.getBean(UserInfo.class);System.out.println(userInfo);}}

5.2.3 重命名Bean

@Bean(name = "Jack")
public UserInfo userInfo1(){return new UserInfo("Jack",18);
}
@Bean(name = {"Lucy","userInfo2"})
public UserInfo userInfo2(){return new UserInfo("Lucy",19);
}
UserInfo userInfo1 = (UserInfo) context.getBean("Jack");
System.out.println(userInfo1);UserInfo userInfo2 = (UserInfo) context.getBean("userInfo2");
UserInfo userInfo3 = (UserInfo) context.getBean("Lucy");
System.out.println(userInfo2);
System.out.println(userInfo3);

5.3 两类注解对比

5.3.1类注解(@Component 全家桶)

类比:

你开了一家餐厅,类注解就像是给不同岗位的员工发工作牌,告诉顾客:“这个人是干啥的”。

注解作用类比场景
@Component通用员工牌,标记 “这是餐厅员工”杂工(哪里需要去哪里)
@Controller前台接待员,专门负责迎接顾客、处理订单服务员(接单、上菜)
@Service厨师,负责做菜的核心业务厨师(炒菜、炖汤)
@Repository仓库管理员,负责食材的存取库管(管冰箱、进货)
@Configuration餐厅老板,专门配置餐厅的各种设备(如咖啡机、收银机)老板(买设备、定规则)

5.3.2方法注解(@Bean

类比: 餐厅需要一些特殊工具(如咖啡机、收银机),但市场上买的都是 “半成品”,需要老板亲自组装。@Bean 就像是老板写的 “组装说明书”。

@Configuration // 餐厅老板
public class RestaurantConfig {@Bean // 组装一台咖啡机public CoffeeMachine coffeeMachine() {CoffeeMachine machine = new CoffeeMachine();machine.setBrand("星巴克"); // 自定义配置machine.setCapacity(100); // 自定义容量return machine;}
}

5.3.3核心区别

维度类注解(如 @Service)方法注解(@Bean)
作用对象员工(类)工具(方法返回的对象)
创建方式餐厅自动招聘(Spring 自动创建实例)老板手动组装(自定义初始化逻辑)
适用场景餐厅内部员工(自己写的类)外部买来的工具(第三方类,如 Redis)

5.3.4协作关系

  1. 类注解:让 Spring 自动扫描并创建组件(如服务员、厨师)。

  2. @Bean:让 Spring 按你的规则创建特殊工具(如咖啡机、收银机)。

例子: 餐厅老板(@Configuration)组装好咖啡机(@Bean),服务员(@Controller)直接用咖啡机给顾客做咖啡,不用操心咖啡机怎么来的。

5.3.5一句话总结

  • 类注解:给员工发工作牌,让 Spring 自动管理员工(类)。

  • @Bean:写工具组装说明书,让 Spring 按你的规则创建工具(对象)。

5.4 扫描路径

Q:使用前面学习的四个注解声明的bean,一定会生效吗?

A:不一定(原因:bean想要生效,还需要被Spring扫描)

使用五大注解声明的bean,要想生效,还需要配置扫描路径,让Spring扫描到这些注解

也就是通过@ComponentScan来配置扫描路径.

了解:

@ComponentScan({"com.example.demo"})
@SpringBootApplication
public class SpringIocDemoApplication {public static void main(String[] args) {//获取Spring上下⽂对象 ApplicationContext context =SpringApplication.run(SpringIocDemoApplication.class, args);//从Spring上下⽂中获取对象 User u1 = (User) context.getBean("u1");//使⽤对象 System.out.println(u1);}
}

    @ComponentScan注解虽然没有显式配置,但是实际上已经包含在了启动类声明注解

    @SpringBootApplication中了

    默认扫描的范围是SpringBoot启动类所在包及其子包

    把启动类放在我们希望扫描的包的路径下,这样我们定义的bean就都可以被扫描到

    6.DI 详解

    依赖注入是一个过程,是指IoC容器在创建Bean时,去提供运行时所依赖的资源,而资源指的就是对象

    简单来说就是把对象取出来放到某个类的属性中

    关于依赖注入,Spring也给我们提供了三种方式:

    1. 属性注入(FieldInjection)

    2. 构造方法注入(ConstructorInjection)

    3. Setter注入(SetterInjection)

    6.1 属性注入

    属性注入是使用@Autowired实现的,将 Service类注入到Controller类中.

    @Controller
    public class UserController {@Autowiredprivate UserService userService;public void say(){System.out.println("UserController say...");userService.say();}
    }
    @Service
    public class UserService {public void say(){System.out.println("UserService say...");}
    }
    @SpringBootApplication
    public class Demo2Application {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(Demo2Application.class, args);UserController userController = context.getBean(UserController.class);userController.say();}}

    6.2 构造方法注入

     

    @Controller
    public class UserController {private final UserService userService;public UserController(UserService userService) {this.userService = userService;}public void say(){System.out.println("UserController say...");userService.say();}
    }

    注意事项:如果类只有一个构造方法,那么@Autowired注解可以省略;如果类中有多个构造方法,那么需要添加上@Autowired来明确指定到底使用哪个构造方法。

     

    @Controller
    public class UserController {private UserService userService;@Autowiredpublic UserController(UserService userService) {System.out.println("有参构造方法");this.userService = userService;}public UserController() {System.out.println("无参构造方法");}public void say(){System.out.println("UserController say...");userService.say();}
    }

    6.3 Setter注入

    Setter注入和属性的Setter方法实现类似,只不过在设置set方法的时候需要加上@Autowired注解

    如下代码所示:

    @Controller
    public class UserController {private UserService userService;@Autowiredpublic void setUserService(UserService userService) {this.userService = userService;}public void say(){System.out.println("UserController say...");userService.say();}
    }

     

    6.4 三种注解优缺点分析

    注入方式优点缺点适用场景 / 推荐版本
    属性注入简洁,使用方便,直接在属性上标注@Autowired等注解即可完成注入1. 仅适用于 IoC 容器,非 IoC 容器环境无法使用;
    2. 使用时才可能暴露 NPE(空指针异常);
    3. 无法注入被final修饰的属性
    简单场景快速开发,Spring 无特定版本强推(但因缺点,实际少用)
    构造函数注入1. 可注入final修饰的属性;
    2. 注入对象不可被修改,保证稳定性;
    3. 依赖在构造阶段执行,对象使用前已完全初始化;
    4. 通用性好,基于 JDK 构造方法,适配各类框架
    注入多个对象时,构造函数参数多,代码繁琐需确保依赖稳定、不可变场景,Spring 4.X 及以上推荐
    Setter 注入方便在类实例化后,重新配置、注入对象,灵活调整依赖1. 无法注入final修饰的属性;
    2. Setter 方法可能被多次调用,注入对象有被修改风险
    需动态调整依赖场景,Spring 3.X 推荐(现在逐渐被构造注入替代)

    6.5 @Autowired存在的问题

    当同⼀类型存在多个bean时,使用@Autowired会存在问题

    报错的原因是,非唯⼀的Bean对象。

    如何解决上述问题呢?Spring提供了以下几种解决方案:

    • @Primary

    • @Qualifier

    • @Resource

    6.5.1 @Primary

    使用@Primary注解:当存在多个相同类型的Bean注入时,加上@Primary注解,来确定默认的实现

    @Component
    public class UserInfoComponent {@Beanpublic UserInfo userInfo(){return new UserInfo("Jack",18);}@Beanpublic UserInfo userInfo1(){return new UserInfo("Jack",18);}@Primary//指定该bean为默认bean的实现 @Beanpublic UserInfo userInfo2(){return new UserInfo("Lucy",19);}}
    @Component
    public class UserComponent {@Autowiredprivate UserInfo ui;public void say(){System.out.println("UserComponent say");System.out.println(ui);}
    }
    @SpringBootApplication
    public class Demo2Application {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(Demo2Application.class, args);UserComponent userComponent = context.getBean(UserComponent.class);userComponent.say();}}

    6.5.2 @Qualifier

    使用@Qualifier注解:指定当前要注入的bean对象。在@Qualifier的value属性中,指定注入的bean的名称。

    • @Qualifier注解不能单独使用,必须配合@Autowired使用

    @Component
    public class UserComponent {@Qualifier("userInfo2")@Autowiredprivate UserInfo ui;public void say(){System.out.println("UserComponent say");System.out.println(ui);}
    }

     

    @Component
    public class UserComponent {@Qualifier("userInfo3")@Autowiredprivate UserInfo ui;public void say(){System.out.println("UserComponent say");System.out.println(ui);}
    }
    @Bean
    public String name(){return "Luka";
    }
    //方法一:
    @Primary
    @Bean
    public String name1(){return "Coco";
    }
    //@Primary
    @Bean
    public UserInfo userInfo3(String name3){return new UserInfo(name3,22);
    }//方法二
    @Bean
    public String name(){return "Luca";
    }
    @Bean
    public UserInfo userInfo3(@Qualifier("name")String name3){return new UserInfo(name3,22);
    }

    如果两个注解同时用的话,@Qualifier优先级更高

    6.5.3 @Resource

    jdk提供的注解

    使用@Resource注解:是按照bean的名称进行注入。通过name属性指定要注入的bean的名称。

    @Component
    public class UserComponent {@Resource(name = "userInfo3")@Autowiredprivate UserInfo ui;public void say(){System.out.println("UserComponent say");System.out.println(ui);}
    }

    @Autowired和@Resource的区别

    1. @Autowired根据类型匹配(优先按照类型匹配,如果同类型有多个对象,按照名称匹配) @Resource根据名称匹配(前提是类型匹配)

    2. @Autowired和@Resource基本原则都是根据类型匹配,但是@Autowired不能指定名称

    3. @Autowired是spring框架提供的注解,而@Resource是JDK提供的注解

    7.总结

    7.1 Spring,Spring Boot和Spring MVC的关系及区别

    Spring:简单来说,Spring是一个轻量级,一站式,模块化,其目的是用于简化企业级应用程序开发

    Spring的主要功能:管理对象,以及对象之间的依赖关系,面向切面编程,数据库事务管理,数据访

    问,web框架支持等.

    但是Spring具备高度可开放性,并不强制依赖Spring,开发者可以自由选择Spring的部分或者全

    部,Spring可以无缝继承第三方框架,比如数据访问框架(Hibernate、JPA),web框架(如Struts、

    JSF)

    SpringMVC:SpringMVC是Spring的一个子框架,Spring诞生之后,大家觉得很好用,于是按照MVC

    模式设计了一个MVC框架(一些用Spring解耦的组件),主要用于开发WEB应用和网络接口,所以,

    SpringMVC 是一个Web框架.

    SpringMVC基于Spring进行开发的,天生的与Spring框架集成.可以让我们更简洁的进行Web层

    开发,支持灵活的URL到页面控制器的映射,提供了强大的约定大于配置的契约式编程支持,非常

    容易与其他视图框架集成,如Velocity、FreeMarker等

    SpringBoot:SpringBoot是对Spring的一个封装,为了简化Spring应用的开发而出现的,中小型

    企业,没有成本研究自己的框架,使用SpringBoot可以更加快速的搭建框架,降低开发成本,让开发

    人员更加专注于Spring应用的开发,而无需过多关注XML的配置和一些底层的实现。

    SpringBoot是个脚手架,插拔式搭建项目,可以快速的集成其他框架进来.

    比如想使用SpringBoot开发Web项目,只需要引入SpringMVC框架即可,Web开发的工作是

    SpringMVC完成的,而不是SpringBoot,想完成数据访问,只需要引入Mybatis框架即可.

    SpringBoot只是辅助简化项目开发的,让开发变得更加简单,甚至不需要额外的web服务器,直接

    生成jar包执行即可.

    最后一句话总结:Spring MVC和Spring Boot都属于Spring,SpringMVC 是基于Spring的一个

    MVC框架,而SpringBoot是基于Spring的一套快速开发整合包。

     

    7.2 Bean的命名

    • 五大注解存储的bean

    ①前两位字母均为大写,bean名称为类名

    ②其他的为类名首字母小写

    ③通过value属性设置@Controller(value="user")

    • @Bean注解存储的bean

    ①bean名称为方法名

    ②通过name属性设置(@Bean(name= {"u1","user1"})

    7.3 常见面试题

    1. 三种注入方式的优缺点

    2. 常见注解有哪些?分别是什么作用?

        web url映射: @RequestMapping

        参数接收和接口响应:@RequestParam,@RequestBody,@ResponseBody

        bean的存储: @Controller, @Service, @Repository, @Component,@Configuration,@Bean
        bean的获取: @Autowired, @Qualifier, @Resource

    3. @Autowired 和@Resource 区别

    4. 说下你对Spring, SpringMVC, Springboot的理解

    http://www.xdnf.cn/news/16331.html

    相关文章:

  • Adobe Animate中文版 v2024.24.0.10.14
  • python---类型转换
  • Flink窗口:解锁流计算的秘密武器
  • 9.SpringBoot Web请求参数绑定方法
  • RTSP|RTMP播放器 in Unity:开源不够用?从工程视角重新定义播放器选型
  • 【优选算法】BFS解决最短路问题(单源)
  • LeetCode 1577.数的平方等于两数乘积的方法数
  • Spring 解析 XML 配置文件的过程(从读取 XML 到生成 BeanDefinition)
  • HarmonyOS NEXT 系列之规范开发三方共享包
  • Java学习-------序列化与反序列化
  • MGRE综合实验
  • 【Linux | 网络】传输层(UDP和TCP)
  • 笔记本键盘的启用和禁用
  • Rust实战:高效开发技巧
  • 强连通分量:Kosaraju算法
  • 使用Python绘制动态樱花
  • CentOS 镜像源配置与 EOL 后的应对策略
  • 【C++篇】STL的关联容器:unordered_map和unordered_set(上篇):哈希表的模拟实现
  • Triton Shared编译
  • Linux网络-------2.应⽤层⾃定义协议与序列化
  • 大模型算法面试笔记——常用优化器SGD,Momentum,Adagrad,RMSProp,Adam
  • Spring MVC设计精粹:源码级架构解析与实践指南
  • AI Coding IDE 介绍:Cursor 的入门指南
  • 深度学习计算(深度学习-李沐-学习笔记)
  • Python 程序设计讲义(23):循环结构——循环控制语句 break 与 continue
  • 【笔记】Einstein关系式 D = ukBT 的推导与应用研究
  • 【自动化运维神器Ansible】Ansible常用模块之hostname模块详解
  • Java面试实战:企业级性能优化与JVM调优全解析
  • 【编号444】雅鲁藏布江(上中下)游8级水系湖泊数据合集
  • cacti漏洞CVE-2022-46169的复现