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

Spring IOCDI————(1)

1,IOC&DI讲解

1,Spring是啥

Spring就是一个开源框架,他们让我们开发变得更加简单,简单来说,Spring就是一个包含了众多工具方法的IOC容器。那么啥是容器呢,我们之前学习的集合,数据结构那块就是容器,用来存储数据容器,这里也是一样,比如Tomcat就是一个Web容器;

2,啥是IOC

那么什么是IOC呢,我们其实在此之前已经使用过了,大家有没有发现,之前在RequestMapping下的代码是一个对象吧,我们调用它里面的方法实现调用功能,但是有个问题啊,我们从来都没new过对象,是不是,从来都没有,但是我们还是可以调用,这个因为这个RequestController和Controller注解中有IOC注解,就是会把这个类交给Spring管理,交给Spring管理,Spring就会帮我们来实例化对象,就是完全交给Spring;IOC简单来说就是Spring提供的存功能;

IOC带来的好处:
1,资源集中管理:IOC容器会帮我们管理一些资源,比如对象,我们在使用的时候,直接过去取就完了;

2,降低代码耦合度,创建实例的时候不用去关心实例的细节;

3,啥是DI

DI的英文翻译为中文的意思就是依赖注入,这是啥意思呢,刚才说了IOC是存,那么DI就是取,

我们可以通过一些列注解来取到我们需要的Bean,Bean就是对象;

3,Spring,Spring MVC,Spring SpringBoot关系:

三者的关系呢:

1,Spring Boot是基于Spring,Spring Boot是基于Spring框架的封装,简化了配置和部署

2,Spring MVC属于Spring,Spring MVC是Spring的Web模块,Spring Boot默认集成MVC

3,Spring Boot整合Spring全家桶,Spring Boot 可以整合 Spring MVC、Spring Data、Spring Security 等模块。


2,IOC详解

IOC即控制反转,我们想掌握IOC就是掌握IOC容器的创建和Bean的存储;

Bean的存储提供了两类注解:
1,类注解

@Controller,@Service,@Repository,@Component,@Configuration

2,方法注解

@Bean

1,类注解

1,@Controller控制器存储
@Controller
public class UserController {public void sayHello(){System.out.println("Hello,Controller");}
}

使用注解就说明吧这个类给Spring管理了,

@SpringBootApplication
public class JavaTest2025519Application {public static void main(String[] args) {//或缺上下文对象ApplicationContext context = SpringApplication.run(JavaTest2025519Application.class, args);//从上下文中或缺对象UserController userController = context.getBean(UserController.class);//使用对象userController.sayHello();}}

 我们可以直接获得到UserController、大家有没有唤醒一些记忆,这个.class怎么那么熟悉呢,这不反射的类加载嘛~,还有这个上下文,大家从哪听过呢,线程那,大家还有记忆没有,这里的上下文呢,指的是当前的运行环境,可以看做容器,容器存储了很多东西,就是运行环境,

我们看看有没有打印出来:

获取成功了,我们成功获取了一个对象,我们这个对象是根据类型创建的,这里我们还没指定Bean,如果有多个Bean呢,我们可能会在注入的时候进行操作,我们在获取这也能操作,我们还提供了其他的getbean方法,这个ApplicationContext继承了BeanFactory的功能,这里常用的三种方法:

1,getBean(类型)

2,getBean(Sting name)

3,getBean(String name,类型)

来试试:
 

        UserController userController = context.getBean(UserController.class);//使用对象userController.sayHello();UserController userController1 = (UserController) context.getBean("userController");userController1.sayHello();UserController userController2 = context.getBean("userController", UserController.class);userController2.sayHello();

三种方法,打印结果:

这里注意这个String就是以小驼峰命名的类名,如果前两个名字都是大写就不动,就一个大写就改成小驼峰的命名规则,我们还没说多个bean的情况呢,具体体现在哪呢,先提前剧透一下,

我们会使用getBean的(String,类型)来获取到类,String对应的就是bean起的名字,不懂没关系,一会儿会讲解bean;

@Controller
@Data
public class UserController2 {private String name;private Integer age;public void sayHello(){System.out.println("Hello,Controller2");}public void say(){System.out.println(name+age);}@Bean("hei1")public UserController2 hei1(){UserController2 userController2 = new UserController2();userController2.setAge(18);userController2.setName("zhangsan");return userController2;}@Bean("hei2")public UserController2 hei2(){UserController2 userController2 = new UserController2();userController2.setAge(19);userController2.setName("zhangsan");return userController2;}
}
        UserController2 userController3 = context.getBean("hei1", UserController2.class);userController3.say();UserController2 userController4 = context.getBean("hei2", UserController2.class);userController4.say();

看打印结果:

 

所以结论嗷,就是我们给Spring的类,Spring会把每个类都起一个名字,根据名称来获取对应的对象,所以是不能重名的;

我们会根据Spring中的bean来对应对象的,比如我们前三个都是UserController用的是一个类型创获取的三个对象,Spring内部创建的,所以地址应该是想同的,后面两个是UserController2中的两个bean,所以地址应该是不同的,我们来试试:
 

        System.out.println(userController);System.out.println(userController1);System.out.println(userController2);;System.out.println(userController3==userController4);

 

 ok,下面来个面试题,

ApplicationContext和BeanFactory

1,获取Bean是beanFactory提供的功能

2,BeanFactory提供了基础访问容器的功能,ApplicationContext是BeanFactory的子类,继承了BeanFactory之外还提供了国际化支持,资源访问支持,事件传播支持,

3,从性能方面,Application更高效,会一次加载并初始化所有的Bean,而BeanFactoty是需要哪个才加载哪个,更加轻量化,有点像单例模式的懒汉和饿汉模式;

2,@Service(服务存储)
@Service
public class UserService {public void sayHello(){System.out.println("Hello,I'm Service");}
}
        UserService userService = context.getBean(UserService.class);userService.sayHello();

 

3,@Repository(仓库存储)
@Repository
public class UserRepository {public void sayHello(){System.out.println("Hello,I'm Repository");}
}
        UserRepository userRepository = context.getBean(UserRepository.class);userRepository.sayHello();

 

4,@Component(组件存储)
@Component
public class UserComponent {public void sayHello(){System.out.println("Hello,I'm Component");}
}
        UserComponent userComponent = context.getBean(UserComponent.class);userComponent.sayHello();

 

5,@Configuration(配置存储)
@Configuration
public class UserConfiguration {public void sayHello(){System.out.println("Hello,I'm Configuration");}
}
        UserConfiguration userConfiguration = context.getBean(UserConfiguration.class);userConfiguration.sayHello();

 

2,为啥要这么多类注解

整这么多注解嘎哈呀,其实他们没有太大区别的,除了@Controller,@Controller可以返回视图大家还记得不,其他的就在语义上有区别,我们是可以进行替换的,但是还是推荐按标准来;这些注解都是@Component的子类;

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

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

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

@Configuration:配置层.处理项⽬中的⼀些配置信息.

3,方法注解

类注解是写在类上的,但是嗷,存在两个问题

1,使用外部包的类是没办法添加类注解的

2,一个类,有多个对象

1,定义一个对象
@Data
public class User {private String name;private Integer age;
}

先来一个User,

@Component
public class UserController3 {@Beanpublic User get(){User user = new User();user.setName("yaoyu");user.setAge(78);return user;}
}

新的控制器,我们想拿到这个User,直接获取想要的对象

        User user = context.getBean(User.class);System.out.println(user);

 

2,定义多个对象
@Component
public class UserController3 {@Beanpublic User get(){User user = new User();user.setName("yaoyu");user.setAge(78);return user;}@Beanpublic User get2(){User user = new User();user.setName("张三");user.setAge(18);return user;}
}

那么接下来如何应对呢,我们后面注入的时候有更好的方法,现在我们可以通过GetBean方法来输入方法名来区分比如get和get2,

        User user1 = context.getBean("get",User.class);System.out.println(user1);User user2 = context.getBean("get2",User.class);System.out.println(user2);

 

3,重命名Bean

我们还可以给Bean起名字:

    @Bean("h1")public User get3(){User user = new User();user.setName("yaoyu21212");user.setAge(78123123);return user;}@Bean("h2")public User get4(){User user = new User();user.setName("张三123");user.setAge(18123123);return user;

 

        User user3 = context.getBean("h1",User.class);System.out.println(user3);User user4 = context.getBean("get3",User.class);System.out.println(user4);

我们看看这个是我们起的名字生效呢,还方法名生效呢, 没有类名为get3,看来还是自定义的名的优先级比较高一点;

        User user3 = context.getBean("h1",User.class);System.out.println(user3);User user5 = context.getBean("h2",User.class);System.out.println(user5);

 

 这下Bean就讲解完了;

4,扫描路径

我们的默认扫描路径就是Application同级以及以下的路径为扫描路径,我们也是可以修改的,使用@ComponentScan({"com.example.demo"})注解,里面是修改的路径,这么说的话如果被那5个类注解修饰的Bean注解也是不一定完全生效的,这是因为可能没配置扫描路径,如果在扫描路径外,那就白忙活了;


3,DI详解

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

相关文章:

  • AG-UI 协议是什么?MCP、A2A 后,AI 领域又新增 AG-UI 协议
  • 50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | Progress Steps (步骤条)
  • Windows环境安装LibreOffice实现word转pdf
  • Python----目标检测(PASCAL VOC数据集)
  • 艾默生流量计与Profibus DP主站转Modbus RTU/TCP网关通讯案例
  • Linux利用多线程和线程同步实现一个简单的聊天服务器
  • 数据库中的属性列数和元组
  • Java POJO接收前端null值设置
  • java+selenium专题->启动浏览器下篇
  • 1.portainer
  • Unity editor文件数UI(支持勾选框)
  • 从 Word2Vec 到 BERT:AI 不止是词向量,更是语言理解
  • 带你搞懂@Valid和@Validated的区别
  • 【Go】从0开始学习Go
  • 【成品设计】基于Arduino的自动化农业灌溉系统
  • 基于DeepSeek的智能客服系统实践与创新
  • 【硬核数学】2. AI如何“学习”?微积分揭秘模型优化的奥秘《从零构建机器学习、深度学习到LLM的数学认知》
  • Java线程:多任务进行
  • 鸿蒙 Location Kit(位置服务)
  • 蓝桥杯1447 砝码称重
  • Flink 快速入门
  • 【LeetCode】大厂面试算法真题回忆(93)--优雅数组
  • 几种数据加密方法
  • 践行“科学智能”!和鲸打造 AI for Science 专属应用
  • docker安装Prometheus+Grafana
  • python如何遍历postgresql所有的用户表
  • OpenHarmony外设驱动使用 (五),Fingerprint_auth
  • ubuntu22.04 卸载ESP-IDF
  • AIGC与数字金融:人工智能金融创新的新纪元
  • [Java][Leetcode middle] 151. 反转字符串中的单词