首页 > 其他分享 >一文带你了解——Spring IoC

一文带你了解——Spring IoC

时间:2024-07-22 16:29:12浏览次数:20  
标签:一文 对象 Spring Bean public bean IoC class

目录

一、IoC介绍

二、Bean存储

2.1 @Controller(控制器存储)

2.1.1 获取bean对象的其他方式

2.1.2 Bean的命名约定

2.2 @Service(服务存储)

2.3 @Repository(仓库存储)

2.4 @Component(组件存储)

2.5 @Configuration(配置存储)

2.6 方法注解@Bean

2.6.1 方法注解的使用

2.6.2 定义多个对象

2.6.3 重命名Bean

2.7 扫描路径


一、IoC介绍

IoC: Inversion of Control (控制反转),也就是说 Spring 是一个"控制反转"的容器。就是将对象的 控制权交给Spring的IOC容器,由IOC容器创建及管理对象,也就是bean的存储。

二、Bean存储

Spring存储对象的注解有:

  1. 类注解:@Controller、@Service、@Repository、@Component、@Configuration
  2. 方法注解:@Bean

2.1 @Controller(控制器存储)

使用@Controller 存储 bean 的代码如下所示:
@Controller // 将对象存储到 Spring 中
public class UserController {
 public void sayHi(){
 System.out.println("hi,UserController...");
 }
}

从Spring容器中获取对象:

@SpringBootApplication
public class SpringIocDemoApplication {
 public static void main(String[] args) {
 //获取Spring上下⽂对象
 ApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args);
 //从Spring上下⽂中获取对象
 UserController bean = context.getBean(UserController.class);
 //使⽤对象
 bean.sayHi();
 }

ApplicationContext,也就是Spring上下文,Spring的运行环境。

运行结果如下:

2.1.1 获取bean对象的其他方式

ApplicationContext 也提供了其他获取bean的方式, ApplicationContext 获取bean对象的功能, 是父类BeanFactory提供的功能。
public interface BeanFactory {
 
 //以上省略...
 
 // 1. 根据bean名称获取bean
 Object getBean(String var1) throws BeansException;
 // 2. 根据bean名称和类型获取bean
 <T> T getBean(String var1, Class<T> var2) throws BeansException;
 // 3. 按bean名称和构造函数参数动态创建bean,只适⽤于具有原型(prototype)作⽤域的bean
 Object getBean(String var1, Object... var2) throws BeansException;
 // 4. 根据类型获取bean
 <T> T getBean(Class<T> var1) throws BeansException;
 // 5. 按bean类型和构造函数参数动态创建bean, 只适⽤于具有原型(prototype)作⽤域的bean
 <T> T getBean(Class<T> var1, Object... var2) throws BeansException;
 
 //以下省略...
}
常用的是上述1,2,4种, 这三种方式,获取到的bean是⼀样的。其中1,2种都涉及到根据名称来获取对象。那么bean的名称是什么呢?

2.1.2 Bean的命名约定

命名约定使用Java标准约定作为实例字段名。 也就是说,bean名称以小写字母开头,然后使用驼峰式大小写。比如:
类名: UserController, Bean的名称为: userController 类名: AccountManager, Bean的名称为: accountManager 类名: AccountService, Bean的名称为: accountService
也有一些特殊情况,当有多个字符并且第一个和第二个字符都是大写时,将保留原始的大写。 这些规则与java.beans.Introspector.decapitalize (Spring在这里使用的)定义的规则相同。比如:
类名: UController, Bean的名称为: UController 类名: AManager, Bean的名称为: AManager

根据这个命名规则,以下方法可以获取Bean:

@SpringBootApplication
public class SpringIocDemoApplication {
 public static void main(String[] args) {
 //获取Spring上下⽂对象
 ApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args);
 //从Spring上下⽂中获取对象
 //根据bean类型, 从Spring上下⽂中获取对象
 UserController userController1 = context.getBean(UserController.class);
 //根据bean名称, 从Spring上下⽂中获取对象
 UserController userController2 = (UserController)context.getBean("userController");
 //根据bean类型+名称, 从Spring上下⽂中获取对象
 UserController userController3 = context.getBean("userController",UserController.class);
 
 System.out.println(userController1);
 System.out.println(userController2);
 System.out.println(userController3);
 }
}
获取bean对象, 是父类BeanFactory提供的功能。

常见面试题:

ApplicationContext   VS   BeanFactory
  • 继承关系和功能方面来说:Spring 容器有两个顶级的接口:BeanFactory 和 ApplicationContext。其中 BeanFactory 提供了基础的访问容器的能力,而 ApplicationContext 属于 BeanFactory 的子类,它除了继承了 BeanFactory 的所有功能之外, 它还拥有独特的特性,还添加了对国际化支持、资源访问支持、以及事件传播等方面的支持。
  • 从性能方面来说:ApplicationContext 是一次性加载并初始化所有的 Bean 对象,而BeanFactory 是需要哪个才去加载哪个,因此更加轻量。(空间换时间)

2.2 @Service(服务存储)

使用@Service 存储 bean 的代码如下所示:

@Service
public class UserService {
   public void sayHi(String name) {
       System.out.println("hi,UserService...");
     }
 }
读取 bean 的代码:
@SpringBootApplication
public class SpringIocDemoApplication {
 public static void main(String[] args) {
 //获取Spring上下⽂对象
 ApplicationContext context = 
SpringApplication.run(SpringIocDemoApplication.class, args);
 //从Spring中获取UserService对象
 UserService userService = context.getBean(UserService.class);
 //使⽤对象
 userService.sayHi();
 }
}

运行结果如下:

2.3 @Repository(仓库存储)

使用@Repository存储bean的代码如下:

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

读取bean的代码:

@SpringBootApplication
public class SpringIocDemoApplication {
 public static void main(String[] args) {
 //获取Spring上下⽂对象
 ApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args);
 //从Spring上下⽂中获取对象
 UserRepository userRepository = context.getBean(UserRepository.class);
 //使⽤对象
 userRepository.sayHi();
 }
}

运行结果如下:

2.4 @Component(组件存储)

使用@Component存储bean的代码如下:

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

读取bean的代码:

@SpringBootApplication
public class SpringIocDemoApplication {
 public static void main(String[] args) {
 //获取Spring上下⽂对象
 ApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args);
 //从Spring上下⽂中获取对象
 UserComponent userComponent = context.getBean(UserComponent.class);
 //使⽤对象
 userComponent.sayHi();
 }
}

 运行结果如下:

2.5 @Configuration(配置存储)

使用 @Configuration 存储 bean 的代码如下所示:
@Configuration
public class UserConfiguration {
 public void sayHi() {
 System.out.println("Hi,UserConfig...");
  }
}

读取bean的代码:

@SpringBootApplication
public class SpringIocDemoApplication {
 public static void main(String[] args) {
 //获取Spring上下⽂对象
 ApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args);
 //从Spring上下⽂中获取对象
 UserConfiguration userConfiguration = context.getBean(UserConfiguration.class);
 //使⽤对象
 userConfiguration.sayHi();
 }
}

 运行结果如下:

NOTE: 为什么要这么多类注解?

查看 @Controller / @Service / @Repository / @Configuration 等注解的源码发现:其实这些注解里面都有一个注解 @Component ,说明它们本身就是属于 @Component 的"子类"。 @Component 是一个元注解,也就是说可以注解其他类注解,如 @Controller , @Service , @Repository 等。 这些注解被称为 @Component 的衍生注解。 @Controller , @Service 和 @Repository 用于 更具体的用例(分别在控制层, 业务逻辑层, 持 久化层), 在开发过程中, 如果你要在业务逻辑层使用  @Component 或@Service,显然@Service是更好的选择。

2.6 方法注解@Bean

类注解是添加到某个类上的,但是存在两个问题:
  • 使用外部包里的类,没办法添加类注解;
  • ⼀个类,需要多个对象,比如多个数据源;
这种场景,我们就需要使用方法注解 @Bean。

2.6.1 方法注解的使用

在 Spring 框架的设计中,方法注解 @Bean 要配合类注解才能将对象正常的存储到 Spring 容器中, 如下代码所示:
@Component
public class BeanConfig {
 @Bean
 public User user(){
 User user = new User();
 user.setName("zhangsan");
 user.setAge(18);
 return user;
 }
}

获取bean对象中的user:

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

运行结果如下:

2.6.2 定义多个对象

@Bean的使用:
@Component
public class BeanConfig {
 @Bean
 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;
 }
}
根据名称来获取bean对象:
@SpringBootApplication
public class SpringIocDemoApplication {
 public static void main(String[] args) {
 //获取Spring上下⽂对象
 ApplicationContext context = 
SpringApplication.run(SpringIocDemoApplication.class, args);
 //根据bean名称, 从Spring上下⽂中获取对象
 User user1 = (User) context.getBean("user1");
 User user2 = (User) context.getBean("user2");
 System.out.println(user1);
 System.out.println(user2);
 }
}

运行结果如下:

@Bean注解的bean,bean的名称就是它的方法名。

2.6.3 重命名Bean

可以通过设置 name 属性给 Bean 对象进行重命名操作,如下代码所示:
@Bean(name = {"u1","user1"})
public User user1(){
 User user = new User();
 user.setName("zhangsan");
 user.setAge(18);
 return user;
}
此时我们使用 u1 就可以获取到 User 对象了,如下所示:
@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);
 }
}

2.7 扫描路径

使用五大注解声明的bean,要想生效,还需要配置扫描路径,让Spring扫描到这些注解。也就是通过在启动类中添加 @ComponentScan 来配置扫描路径。默认扫描的范围是SpringBoot启动类所在包及其子包。
@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);
 }
}

但是此做法不做推荐,那么推荐做法为:

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

标签:一文,对象,Spring,Bean,public,bean,IoC,class
From: https://blog.csdn.net/m0_60462557/article/details/140608198

相关文章

  • 初用IDEA的springboot的第二步
    了解分层思想将一个方法的代码,拆分到各个部分中,分层的意义是为了团队合作更加方便1.在项目src/main目录下新建java(源文件夹)和resources(资源文件夹)目录2.定义包结构及代表意义web:控制层,定义接口,接收前端客户的需求/请求,传入后端进行解析并将结果传回(接收参数,返回数据)sercic......
  • 【计算机优质毕设】基于SpringBoot的生鲜交易系统
    前言:我是IT源码社,从事计算机开发行业数年,专注Java领域,专业提供程序设计开发、源码分享、技术指导讲解、定制和毕业设计服务......
  • spring —— IoC 容器(一)
    IoC不是一种技术,而是一种设计思想,旨在降低代码之间的耦合性。Spring通过IoC容器管理所有Java对象的实例化和初始化,控制对象与对象之间的依赖关系。一、基于XML管理bean(一)通过XML获取beanpublicclassUser{privateStringname;privateintage;......
  • Spring Boot 的无敌描述
    1/spring-boot-app2├──src3│ ├──main4│ │ ├──java5│ │ │ └──com6│ │ │   └──example7│ │ │     └──springbootapp8│ │ │       ├──Application.jav......
  • Mailspring邮件服务器如何配置做邮件管理?
    Mailspring邮件服务器性能调优的策略?如何部署服务器?Mailspring是一款功能强大的邮件客户端,支持多种邮件服务,同时具有直观的用户界面和丰富的功能。那么,如何配置Mailspring邮件服务器来进行邮件管理呢?AokSend将详细介绍相关步骤和技巧。Mailspring邮件服务器:下载安装可以从M......
  • 一文看懂免单优选模式
    在日新月异的电商领域,一种名为“免单优选”的创新销售模式正悄然兴起,它以独特的魅力吸引着广大消费者的目光。这种模式的核心理念简单而直接:通过免单奖励激发购买热情,让购物不再是单纯的消费,而是一场充满惊喜与回馈的旅程。特点概览合法合规:免单优选模式严格遵守国家法律法规......
  • SpringBoot原理解析(二)- Spring Bean的生命周期以及后处理器和回调接口
    SpringBoot原理解析(二)-SpringBean的生命周期以及后处理器和回调接口文章目录SpringBoot原理解析(二)-SpringBean的生命周期以及后处理器和回调接口1.Bean的实例化阶段1.1.Bean实例化的基本流程1.2.Bean实例化图例1.3.实例化阶段的后处理器1.3.1.实例化阶段后处理器......
  • 嵌入式C++、FreeRTOS、MySQL、Spring Boot和MQTT协议:智能零售系统详细流程介绍(代码示
    项目概述随着科技的发展,零售行业正经历着一场数字化转型。智能零售系统通过集成嵌入式技术和大数据分析,为商家提供了高效的运营管理工具。该系统的核心目标是提升顾客体验、优化库存管理、降低运营成本以及实现精准营销。本项目将结合多种技术栈,包括嵌入式硬件、嵌入式软件、......
  • SpringBoot+ Sharding Sphere 轻松实现数据库字段加解密
    一、介绍在实际的软件系统开发过程中,由于业务的需求,在代码层面实现数据的脱敏还是远远不够的,往往还需要在数据库层面针对某些关键性的敏感信息,例如:身份证号、银行卡号、手机号、工资等信息进行加密存储,实现真正意义的数据混淆脱敏,以满足信息安全的需要。那在实际的业务开发过程......
  • SpringBoot利用MyBatis连接Mysql数据库时常见启动报错
    目录报错情况报错情况一:​编辑报错情况二:解决步骤一、解决命名问题1.mapper层的id是否和Dao层的方法名字相同2.检查namespace与Dao层的文件地址相同二、解决注解问题1.检查Controller层的注解是否正确和完整2.Dao层或者Mapper层的注解3.pojo层:实体类层Data注解(用来......