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

【Java笔记】Spring IoC DI

目录

  • Spring IoC & DI
    • 1. IoC
      • 1.1 Bean的存储
        • 1.1.1 类注解
        • 1.1.2 方法注解 @Bean
        • 1.1.3 重命名
        • 1.1.4 Spring扫描路径
    • 2. DI

Spring IoC & DI

Spring两个核心思想:IoC & AOP

Spring相当于一个容器,IoC就是把对象存放在Spring容器中,让Spring帮我们管理对象,DI就是从Ioc容器中取出对象并注入给另一个对象,简言之,IoC就是存对象,DI就是取对象

1. IoC

注解:@Component,表示BookService这个对象已经交给Spring管理了,Spring帮我们new了一个对象

@Component
public class BookService {...
}

注解 :@Autowired表示从Spring容器中取出对象,赋值给bookService属性并且注入给BookController对象

public class BookController {@Autowiredprivate BookService bookService;...
}

1.1 Bean的存储

两类注解:

  1. 类注解 - 五大注解:@Controller @Service @Repository @Component @Configuration
  2. 方法注解:@Bean
1.1.1 类注解
@Controller
public class UserController {...
}

@SpringBootApplication在那个类上,哪个类就是启动类

ApplicationContext可以理解为Spring容器,Spring管理的对象都在这个容器中,需要从这里边拿到对象

通过 .getBean() 拿到对象,再执行对象中的方法,下代码示例是从ApplicationContext容器中获取对象的三种方法,三种方法获取到的是同一个对象:

@SpringBootApplication
public class SpringIocDemoApplication {public static void main(String[] args) {// 1. 通过类名获取对象ApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args);UserController bean = context.getBean(UserController.class);System.out.println(bean);bean.sayHi();// 2. 通过BeanName获得对象UserController userController = (UserController)context.getBean("userController");System.out.println(userController);userController.sayHi();// 3. 通过类名加类型获取对象UserController userController1 = context.getBean("userController", UserController.class);System.out.println(userController1);userController1.sayHi();}
}

BeanName默认是类的小驼峰写法;当类名前两个字母都是大写时,BeanName就是类名

五个注解都可以让Spring帮助管理对象

@Controller @Service @Repository @Configuration 都是 @Component 的衍生注解

不同的注解的功能相同,但是表示的含义不同,类似车牌号

@Controller定位最清晰,表示接收请求的类通常使用@Controller或@RestController注解,不推荐使用其他注解(如@Service、@Repository等)

  1. @Controller :对应三层架构的表现层
  2. @Service:对应业务逻辑层
  3. @Repository:对应数据层
  4. @Configuration:表示配置层
  5. @Component:表示组件
1.1.2 方法注解 @Bean

@Bean必须搭配五大注解使用,因为如果类都没有交给Spring管理,那么方法是不会在Spring容器中找到的,一般搭配@Configuration @Component都可以

将第三方的方法交给Spring管理使用@Bean

@Bean注解定义的bean,beanName为方法名,不是类的小驼峰写法了

同一个类型有多个bean只能通过以下的两种方式获取对象,需要加上beanName:

UserInfo bean = context.getBean("user1",UserInfo.class);
System.out.println(bean);UserInfo bean2 = context.getBean("user2",UserInfo.class);
System.out.println(bean2);
1.1.3 重命名

五大注解的beanName重命名

@Repository("ur")
public class UserRepository {public void doRepository() {...}
}
UserRepository bean = context.getBean("ur", UserRepository.class);
bean.doRepository();

@Bean的beanName重命名

@Bean(name = "zhangsan")
public UserInfo user1() {UserInfo userInfo = new UserInfo(1, "zhangsan", 12);return userInfo;
}
UserInfo bean = context.getBean("zhangsan",UserInfo.class);

也可以有多个重命名:

@Bean(name = {"user1", "zhangsan"})
1.1.4 Spring扫描路径

启动类所在的路径就是默认的扫描路径,也可以通过在类上加注解@ComponentScan(basePackages = “路径”)指定扫描路径。

2. DI

DI就是依赖注入;

Spring依赖注入的三种方式:

  1. 属性注入:使用注解@Autowired

    • 构造方法注入:如果只有一个构造方法,@Autowired可以省略(Spring 4.3+版本);

    • 如果存在多个构造方法,如果无参的构造方法和有参的构造方法同时存在,默认使用无参的构造方法;如果要使用有参的构造方法,需要在有参的构造方法加上@Autowired。优先使用加@Autowired注解的构造方法,因为@Autowired优先级最高,没有@Autowired Spring就会找无参的构造方法,如果没有无参的构造方法会报错

    	private UserService userService;	public UserController2() {}// 构造方法注入@Autowiredpublic UserController2(UserService userService) {this.userService = userService;}
    
    1. Setter注入
      setter方法也需要搭配@Autowired注解
    @Autowired
    public void setUserService(UserService userService) {this.userService = userService;
    }
    

程序员通常使用属性注入的方式

当一个类中存在多个方法时,从这个类中取出方法需要使用:

  1. @Primary指定默认的bean

  2. @Qualifier(“beanName”)指定bean

  3. 当@Primary、@Qualifier(“beanName”)同时存在使用@Qualifier(“beanName”)

  4. 使用@Resource(name = “beanName”),作用等同于 @Qualifier(“beanName”) + @Autowired

企业中更多使用的是@Resource(name = “beanName”) 和 @Autowired

代码示例:

//    @Autowired
//    @Qualifier("user2")@Resource(name = "user2")private UserInfo userInfo;
http://www.xdnf.cn/news/10250.html

相关文章:

  • YOLOv8 移动端升级:借助 GhostNetv2 主干网络,实现高效特征提取
  • 【CC协议】知识共享许可协议(Creative Commons Licenses)体系解析
  • 注销微软账户
  • android 媒体框架之MediaCodec
  • MySQL中COUNT(*)、COUNT(1)和COUNT(字段名)的深度剖析与实战应用
  • 谷歌:贝叶斯框架优化LLM推理反思
  • CMake指令:list()
  • MySQL(48) 什么是ZEROFILL属性?
  • 宇树机器狗go2添加3d雷达(下)添加velodyne系列雷达
  • 《高等数学》(同济大学·第7版) 第一节《映射与函数》超详细解析
  • 数据库只更新特定字段的两种方式(先读后写 vs. 动态组织 SQL)-golang SQLx 实现代码(动态组织 SQL)
  • 索引的选择与Change Buffer
  • Linux进程信号
  • 车载诊断架构SOVD --- 车辆发现与建连
  • 项目:贪吃蛇实现
  • AI与智能驾驶的关系和原理:技术融合与未来展望-优雅草卓伊凡一、AI大模型基础原理与智能驾驶
  • 【Linux系列】Linux/Unix 系统中的 CPU 使用率
  • C++23 已移除特性解析
  • 电子电路:怎么理解时钟脉冲上升沿这句话?
  • ASP.NET Core SignalR的基本使用
  • 《深入解析SPI协议及其FPGA高效实现》-- 第一篇:SPI协议基础与工作机制
  • Python编程基础(一) | 变量和简单数据类型
  • git下载和安装(完整版)
  • 什么是特性阻抗
  • ArcPy错误处理与调试技巧(2)
  • Mybatis ORM SpringORM
  • 计算机视觉---GT(ground truth)
  • C# 成员函数中如何拿到当前所在类的名字?
  • 使用 HTML + JavaScript 实现一个日历任务管理系统
  • HackMyVM-First